/**
 * Created by sjg on 16/11/29.
 */

var ItbUserModel = require('../../../common/mysql/mapping/ItbUserModel');
var ItbDocumentModel = require('../../../common/mysql/mapping/ItbDocumentModel');
var ItbFeedbackModel = require('../../../common/mysql/mapping/ItbFeedbackModel');
var TgUserDocModel = require('../../../common/mysql/mapping/TgUserDocModel');
var ItbCollectModel = require('../../../common/mysql/mapping/ItbCollectModel');
var ItbPartnerModel = require('../../../common/mysql/mapping/ItbPartnerModel');
var ItbPartnerApplicationModel = require('../../../common/mysql/mapping/ItbPartnerApplicationModel');
var ItbPartnerIncomeModel = require('../../../common/mysql/mapping/ItbPartnerIncomeModel');
var ItbPartnerCustModel = require('../../../common/mysql/mapping/ItbPartnerCustModel');
var TgDesignDocModel = require('../../../common/mysql/mapping/TgDesignDocModel');
var ItbTemplateModel = require('../../../common/mysql/mapping/ItbTemplateModel');
var ItbItemsModel = require('../../../common/mysql/mapping/ItbItemsModel');
var ItbCouponModel = require('../../../common/mysql/mapping/ItbCouponModel');
var ItbNotificationModel = require('../../../common/mysql/mapping/ItbNotificationModel');
var ItbNotifyUserModel = require('../../../common/mysql/mapping/ItbNotifyUserModel');
var ItbPartnerAreaModel = require('../../../common/mysql/mapping/ItbPartnerAreaModel');
var ItbAddressModel = require('../../../common/mysql/mapping/ItbAddressModel');
var ItbProductVer = require('../../../common/mysql/mapping/ItbProductVer');
var ItbDatumTmplModel = require('../../../common/mysql/mapping/ItbDatumTmplModel');
var ItbDatumInfoModel = require('../../../common/mysql/mapping/ItbDatumInfoModel');
var ItbMemberModel = require('../../../common/mysql/mapping/ItbMemberModel');
var ItbTradeOrderModel = require('../../../common/mysql/mapping/ItbTradeOrderModel');
var ItbPaymentHisModel = require('../../../common/mysql/mapping/ItbPaymentHisModel');
var ItbPartnerSaleRankModel = require('../../../common/mysql/mapping/ItbPartnerSaleRankModel');
var ItbExpTrackInfoModel = require('../../../common/mysql/mapping/ItbExpTrackInfoModel');
var SJGTGV3 = require('./../../sjg/common/tg3/SJGTGV3');

var CONFIG = require('../../../common/config');
var CODE = require('../../../common/code');
var async = require( 'async'); // 同步控制
var crypto = require('crypto');
var moment = require('moment');  // 日期格式化

var hxUtil = require('./hxUtil');
var payUtil = require('./payUtil');

var superagent = require('superagent');
var callFuncUtil = require('../util/callFuncUtil');
var printUtil = require('./printUtil');

var usersUtil = (function(){
    function usersUtil(){
    }


    //----------------------------------------------------------------
    // 返回方法
    usersUtil.ret_func_json = function (success, msg, data, res){
        var obj = {
            success: success,
            msg: msg,
            data: data
        };
        // 返回
        res.set('Content-Type', 'application/json');
        res.json(obj);
    };
    //----------------------------------------------------------------
    /* 根据微信unionId和微信opneId查询用户
     * 参数：wxUnionId:
     * 参数：wxOpenId:
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.get_mobileUserByWx = function (wxUnionId, wxOpenId,callback){
        var entity = new ItbUserModel({
            wechat_token_union:wxUnionId,
            wechat_token:wxOpenId,
            del_flg:0
        });

        var pageSize = 1;
        entity.findFromDB(function(error,items) {
            if (error) {
                console.log(error);
                return callback(error,null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        },0,pageSize);
    }
    //----------------------------------------------------------------
    /* 根据微信unionId或者微信opneId查询用户
     * 参数：wxUnionId:
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.get_mobileUserByWxUnionId  = function (wxUnionId,callback){
        var entity = new ItbUserModel({
            wechat_token_union:wxUnionId,
            del_flg:0
        });

        var pageSize = 1;
        entity.findFromDB(function(error,items) {
            if (error) {
                console.log(error);
                return callback(error,null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        },0,pageSize);
    }
    //----------------------------------------------------------------
    /* 根据微信unionId或者微信opneId查询用户
     * 参数：wxUnionId:
     * 参数：wxOpenId:
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.get_mobileUserByWxUnionIdOrOpenId  = function (wxUnionId, wxOpenId,callback){
        var entity = new ItbUserModel({
            wechat_token_union:wxUnionId,
            wechat_token:wxOpenId,
            del_flg:0
        });

        var pageSize = 1;
        entity.findByUnionIdOrOpenId(function(error,items) {
            if (error) {
                console.log(error);
                return callback(error,null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        },0,pageSize);
    }
    //----------------------------------------------------------------
    /* 根据微信opneId查询用户
     * 参数：wxOpenId:
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.get_mobileUserByWxOpenId  = function (wxOpenId,callback){
        var entity = new ItbUserModel({
            wechat_token:wxOpenId,
            del_flg:0
        });

        var pageSize = 1;
        entity.findFromDB(function(error,items) {
            if (error) {
                console.log(error);
                return callback(error,null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        },0,pageSize);
    }
    //----------------------------------------------------------------
    /* 根据mobile查询用户
     * 参数：mobile: 手机号
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.get_mobileUserByMobile = function (mobile,callback){
        var entity = new ItbUserModel({
            mobile:mobile,
            del_flg:0
        });

        var pageSize = 1;
        entity.findFromDB(function(error,items) {
            if (error) {
                console.log(error);
                return callback(error,null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        },0,pageSize);
    }
    //----------------------------------------------------------------
    /* ［网站用］根据微信unionId和微信opneId查询用户
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxOpenId: 微信OpenId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 user_item：ItbUserModel
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.wxLoginWithExistMobileUserForWeb =function(wxUnionId,wxHeader,wxNickName,uuid,user_item,callback){
        // 更新用户信息
        // 如果存在openID且与UnionID对应，则也更新到U
        if(user_item.wechat_token_union==wxUnionId){
            usersUtil.updateUserByWxAndMobile(wxUnionId, user_item.wechat_token,wxHeader, wxNickName,uuid,  user_item.mobile, user_item.user_id,function(error, user_item){
                return callback(error, user_item);
            });
        }else{
            usersUtil.updateUserByWxAndMobileAndClearOpenId(wxUnionId,wxHeader, wxNickName,uuid,  user_item.mobile, user_item.user_id,function(error, user_item){
                return callback(error, user_item);
            });
        }

    }

    //----------------------------------------------------------------
    /* 根据微信unionId和微信opneId查询用户
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxOpenId: 微信OpenId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 user_item：ItbUserModel
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.wxLoginWithExistMobileUser =function(wxUnionId,wxOpenId,wxHeader,wxNickName,uuid,user_item,callback){

        //取得手机OpenID对应的用户账户f,从f中排出U得到F
        usersUtil.getOtherUserByOpenIDFromDB(wxOpenId,user_item.user_id, function(error, user_items){
            if(error){
                return callback(error, null);
            }
            // 合并F的文档到U,并删除F
            usersUtil.moveDocFromSourceAndRemoveSouce(user_items, user_item.user_id, function(error){
                if(error){
                    return callback(error, null);
                }

                // 更新用户信息
                usersUtil.updateUserByWxAndMobile(wxUnionId, wxOpenId,wxHeader, wxNickName,uuid,  user_item.mobile, user_item.user_id,function(error, user_item){
                    return callback(error, user_item);
                });
            });
        });



    }


    //----------------------------------------------------------------
    /* 合并F的文档到U,并删除F
     * 参数 from_user_items: 微信UnionId
     * 参数 to_user_id：user_id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *
     */
    usersUtil.moveDocFromSourceAndRemoveSouce=function(from_user_items,to_user_id,callback){
        if(from_user_items==null || from_user_items.length==0){
            return callback(null);
        }

        // 同步更新
        var asyncFuncs = [];
        for (var i in from_user_items) {
            asyncFuncs.push((function (index, user_item) {
                return function (asyncCallback) {
                    usersUtil.moveDocFrom(user_item.user_id, to_user_id, asyncCallback);
                }
            })(i, from_user_items[i])); // 利用闭包解决动态参数传递问题
        }
        async.parallel(asyncFuncs, function (error, results) {
            if (error) {
                return callback(error, null);
            }

            return usersUtil.removeSouce(from_user_items, callback);
        });
    }
    //----------------------------------------------------------------
    /* 并删除F
     * 参数 from_user_items: 微信UnionId
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *
     */
    usersUtil.removeSouce=function(from_user_items,callback){
        if(from_user_items==null || from_user_items.length==0){
            return callback(null);
        }

        // 同步更新
        var asyncFuncs = [];
        for (var i in from_user_items) {
            asyncFuncs.push((function (index, user_item) {
                return function (asyncCallback) {
                    var delEnt = new ItbUserModel({
                        user_id: user_item.user_id,
                        del_flg: 1,
                    });
                    delEnt.updateToDB(function(error){
                        asyncCallback(error,null);
                    });
                }
            })(i, from_user_items[i])); // 利用闭包解决动态参数传递问题
        }
        async.parallel(asyncFuncs, function (error, results) {
            if (error) {
                return callback(error);
            }

            return callback(null);
        });
    }


    //----------------------------------------------------------------
    /**
     * 转移用户文档, 从第一个用户名下转移到第二个用户名下
     * from_user_id 被转移文档的用户id
     * to_user_id   转移至 toUser 名下
     * callback 回调
     *          callbac 参数
     *              err: 错误信息
     * */
    usersUtil.moveDocFrom = function(from_user_id, to_user_id, callback) {

        // ppt 文档
        var docEnt = new ItbDocumentModel({
            user_id_from : from_user_id,
            user_id_to : to_user_id
        });
        // 转移用户 ppt 文档
        docEnt.moveDocByUser(function(err, ret){
            if (err) {
                console.log('usersUtil.js [moveUserDoc] move Doc Err: ' + err);
                return callback(err);
            }

            // 转移用户竖屏文档
            var tgEnt = new TgUserDocModel({
                user_id_from : from_user_id,
                user_id_to : to_user_id
            });
            tgEnt.moveDocByUser(function(err2,ret2){
                if (err2) {
                    console.log('usersUtil.js [moveUserDoc] move TgDoc Err: ' + err2);
                    return callback(err);
                }

                return callback(null);
            });
        });
    };

    //----------------------------------------------------------------
    /* 取得UnionID对应的账户s,并排除U的到S
     * 参数 wxUnionId: 微信UnionId
     * 参数 user_id：user_id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel的数组
     *
     */
    usersUtil.getOtherUserByUnionIDFromDB = function(wxUnionId,user_id,callback){
        var unionEntity = new ItbUserModel({
            wechat_token_union: wxUnionId,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (error, items) {
            if(error){
                return callback(error, null);
            }
            items = items||[];
            for(var i=items.length-1;i>=0;i--){
                if(items[i].user_id==user_id){
                    items.splice(i,1);
                }
            }
            return callback(null, items);
        });
    }

    //----------------------------------------------------------------
    /* 取得手机OpenID对应的用户账户f,从f中排出U得到F
     * 参数 wxOpenId: 微信UnionId
     * 参数 user_id：user_id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel的数组
     *
     */
    usersUtil.getOtherUserByOpenIDFromDB = function(wxOpenId,user_id,callback){
        var unionEntity = new ItbUserModel({
            wechat_token: wxOpenId,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (error, items) {
            if(error){
                return callback(error, null);
            }
            items = items||[];
            for(var i=items.length-1;i>=0;i--){
                if(items[i].user_id==user_id){
                    items.splice(i,1);
                }
            }
            return callback(null, items);
        });
    }

    //----------------------------------------------------------------
    /* 取得微信OpenID对应的用户账户
     * 参数 wxOpenId: 微信UnionId
     * 参数 user_id：user_id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel的数组
     *
     */
    usersUtil.getUserByOpenIDFromDB = function(wxOpenId,callback){
        var unionEntity = new ItbUserModel({
            wechat_token: wxOpenId,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (error, items) {
            if(error){
                return callback(error, null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        });
    }

    /* 取得微信unionId对应的用户账户
     * 参数 wxUnionId: 微信UnionId
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user :用户表行信息
     *
     */
    usersUtil.getUserByUnionIDFromDB = function(wxUnionId,callback){
        var unionEntity = new ItbUserModel({
            wechat_token_union: wxUnionId,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (error, items) {
            if(error){
                return callback(error, null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        });
    }

    //----------------------------------------------------------------
    /* 根据微信UnionID获取对应的用户账户
     * 参数 wxOpenId: 微信UnionId
     * 参数 user_id：user_id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel的数组
     *
     */
    usersUtil.getUserByUnionIDFromDB = function(wxUnionId,callback){
        var unionEntity = new ItbUserModel({
            wechat_token_union: wxUnionId,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (error, items) {
            if(error){
                return callback(error, null);
            }
            if(items.length==0){
                return callback(null,null);
            }
            return callback(null, items[0]);
        });
    }

    //----------------------------------------------------------------
    /* 更新用户信息
     * 参数 user_id：用户id
     * 参数 wxUnionId: 微信UnionId
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *
     */
    usersUtil.updateWxById = function(user_id, wxUnionId,wxOpenId,callback){
        var unionEntity = new ItbUserModel({
            user_id: user_id,
            wechat_token_union:wxUnionId,
            wechat_token:wxOpenId
        });
        unionEntity.updateToDB(function(error){
            if(error){
                return callback(error, null);
            }
            return callback(null);
        });
    }
    //----------------------------------------------------------------
    /* 更新用户信息
     * 参数 user_id：用户id
     * 参数 wxUnionId: 微信UnionId
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *
     */
    usersUtil.updateUnionById = function(user_id, wxUnionId,callback){
        var unionEntity = new ItbUserModel({
            user_id: user_id,
            wechat_token_union:wxUnionId,
        });
        unionEntity.updateToDB(function(error){
            if(error){
                return callback(error, null);
            }
            return callback(null);
        });
    }


    //----------------------------------------------------------------
    /* 更新用户信息，并清除OpenID
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 mobile：手机号
     * 参数 user_id：用户id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel
     *
     */
    usersUtil.updateUserByWxAndMobileAndClearOpenId = function(wxUnionId,wxHeader, wxNickName,uuid,  mobile, user_id,callback){
        var unionEntity = new ItbUserModel({
            user_id: user_id,
            del_flg: 0
        });
        if(wxUnionId){
            unionEntity.wechat_token_union = wxUnionId;
        }
        // clear openID
        unionEntity.wechat_token = null;

        if(wxHeader){
            unionEntity.head_url = wxHeader;
        }
        if(wxNickName){
            unionEntity.wechat_nickname = wxNickName;
        }
        if(uuid){
            unionEntity.uuid = uuid;
        }
        if(mobile){
            unionEntity.mobile = mobile;
        }

        unionEntity.updateToDB(function(error){
            if(error){
                return callback(error, null);
            }
            var retData={
                user_id:user_id,
                user_type:1,
                nickname:'',
                head_url:wxHeader,
                sign:'',
                wechat_token:null,
                wechat_token_union:wxUnionId,
                wechat_nickname:wxNickName,
                mobile:mobile,
                uuid:uuid
            };
            return callback(null, retData);
        });
    }

    //----------------------------------------------------------------
    /* 更新用户信息
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxOpenId: 微信OpenId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 mobile：手机号
     * 参数 user_id：用户id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel
     *
     */
    usersUtil.updateUserByWxAndMobile = function(wxUnionId, wxOpenId,wxHeader, wxNickName,uuid,  mobile, user_id,callback){
        var unionEntity = new ItbUserModel({
            user_id: user_id,
            del_flg: 0
        });
        if(wxUnionId){
            unionEntity.wechat_token_union = wxUnionId;
        }
        if(wxOpenId){
            unionEntity.wechat_token = wxOpenId;
        }
        if(wxHeader){
            unionEntity.head_url = wxHeader;
        }
        if(wxNickName){
            unionEntity.wechat_nickname = wxNickName;
        }
        if(uuid){
            unionEntity.uuid = uuid;
        }
        if(mobile){
            unionEntity.mobile = mobile;
        }

        unionEntity.updateToDB(function(error){
            if(error){
                return callback(error, null);
            }
            var retData={
                user_id:user_id,
                user_type:1,
                nickname:'',
                head_url:wxHeader,
                sign:'',
                wechat_token:wxOpenId,
                wechat_token_union:wxUnionId,
                wechat_nickname:wxNickName,
                mobile:mobile,
                uuid:uuid
            };
            return callback(null, retData);
        });
    }

    //----------------------------------------------------------------
    /* 取得手机OpenID对应的用户账户
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxOpenId: 微信OpenId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 mobile：手机号
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          user_items:ItbUserModel
     *
     */
    usersUtil.insertUserByWxAndMobile = function(wxUnionId, wxOpenId,wxHeader, wxNickName,uuid,  mobile, callback){
        // 未找到则注册默认用户
        var DEF_PW = 'e10adc3949ba59abbe56e057f20f883e';
        var DEF_PW = 'ED035DE6D7392A03642D246BC95D06A2';// DefaultFromWechatBindMobile
        var newEnt = new ItbUserModel({
            //user_name :'Wechat_User',// todo
            user_type :1,
            head_url:wxHeader,
            wechat_token: wxOpenId,
            wechat_token_union:wxUnionId,
            wechat_nickname: wxNickName,
            mobile:mobile,
            password  :DEF_PW,
            uuid      :uuid,
        });
        newEnt.saveToDB(function(error, user_id){
            if(error){
                console.log('usersUtils.js [insertUserByWxAndMobile] create user Err:'+error);
                return callback(error,null);
            }


            // 兑换优惠券并尝试添加为下线 //todo
            usersUtil.exchgCouponAndTryAddPartnerCustom(mobile, function () {

                var retData={
                    user_id:user_id,
                    user_type:1,
                    nickname:'',
                    head_url:wxHeader,
                    sign:'',
                    wechat_token:wxOpenId,
                    wechat_token_union:wxUnionId,
                    wechat_nickname:wxNickName,
                    mobile:mobile,
                    uuid:uuid
                };
                return callback(null, retData);

            });
        });
    }

    //----------------------------------------------------------------
    /* ［网站用］根据微信unionId和微信opneId查询用户
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 mobile：手机号
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.wxLoginWithoutExistMobileUserForWeb =function(wxUnionId,wxHeader,wxNickName,uuid,mobile,callback){
        // 根据UnionId查找用户信息
        usersUtil.getUserByUnionIDFromDB(wxUnionId, function(error, user_item){
            if(error){
                return callback(error, null);
            }
            // 如果找不到，则新建
            if(user_item==null){
                usersUtil.insertUserByWxAndMobile(wxUnionId,null,wxHeader,wxNickName,uuid,mobile,function(error, user_item){
                    if(error){
                        return callback(error, null);
                    }
                    return callback(null,user_item);
                });
            }else{
                // 找到就更新手机号
                usersUtil.updateUserByWxAndMobile(wxUnionId, user_item.wechat_token,wxHeader, wxNickName,uuid,  mobile, user_item.user_id,function(error, user_item){
                    if(error){
                        return callback(error, null);
                    }
                    return callback(null,user_item);
                });

            }
        })

    }


    //----------------------------------------------------------------
    /* 根据微信unionId和微信opneId查询用户
     * 参数 wxUnionId: 微信UnionId
     * 参数 wxOpenId: 微信OpenId
     * 参数 wxHeader： 微信头像地址
     * 参数 wxNickName： 微信 昵称
     * 参数 uuid: 设备标识符
     * 参数 mobile：手机号
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data:ItbUserModel类型
     *
     */
    usersUtil.wxLoginWithoutExistMobileUser =function(wxUnionId,wxOpenId,wxHeader,wxNickName,uuid,mobile,callback){
        // 转移可能存在的账户（网站微信登陆后的用户：有mobile和unionId，无openId）
        function inner(wxUnionId,user_item,callback){
            //取得UnionID对应的账户s 从s中排除U得到S
            usersUtil.getOtherUserByUnionIDFromDB(wxUnionId,user_item.user_id, function(error, user_items){
                if(error){
                    return callback(error, null);
                }
                // 合并S的文档到U 并删除S
                usersUtil.moveDocFromSourceAndRemoveSouce(user_items, user_item.user_id, function(error){
                    if(error){
                        return callback(error, null);
                    }
                    return callback(null, user_item);
                });
            });
        }
        // 先查询是否存在 openid 用户
        usersUtil.getUserByOpenIDFromDB(wxOpenId, function(error, user_item){
            if(error){
                return callback(error, null);
            }
            // 不存在 openid 用户, 查询 unionid 用户
            if(user_item==null){
                // openId 对应用户不存在, 检测 unionId 对应用户, 是否存在(只有 unionid 对应的用户, 目前的来源是 微信小程序), add by wangjun 2017-09-25
                usersUtil.getUserByUnionIDFromDB(wxUnionId, function(getUnionUserErr, userInfo){
                   // 存在 unionId 用户, 则合并
                    if(userInfo) {
                        usersUtil.updateUserByWxAndMobile(wxUnionId, wxOpenId,wxHeader, wxNickName,uuid,  mobile, userInfo.user_id,function(error, user_item){
                            if(error){
                                return callback(error, null);
                            }
                            return inner(wxUnionId,user_item,callback);
                        });
                    }
                    // 连 union id 用户都没有, 则合并
                    else {
                        usersUtil.insertUserByWxAndMobile(wxUnionId,wxOpenId,wxHeader,wxNickName,uuid,mobile,function(error, user_item){
                            if(error){
                                return callback(error, null);
                            }
                            return inner(wxUnionId,user_item,callback);
                        });
                    }
                });
            }
            // 存在 openid 用户, 合并
            else{
                usersUtil.updateUserByWxAndMobile(wxUnionId, wxOpenId,wxHeader, wxNickName,uuid,  mobile, user_item.user_id,function(error, user_item){
                    if(error){
                        return callback(error, null);
                    }
                    return inner(wxUnionId,user_item,callback);
                });
            }
        })

    }

    //----------------------------------------------------------------
    // 根据 ItbUserModel 创建返回数据
    usersUtil.retDataWithITBUserModel = function retDataWithITBUserModel(userModel){
        console.log("usersUtil.js [retDataWithITBUserModel] userModel json: " + JSON.stringify(userModel));
            var retData = {
                user_id:userModel.user_id,
                user_type:userModel.user_type,
                nickname:userModel.nickname||'',
                head_url:userModel.head_url||'',
                sign:userModel.signature||'',
                wxuid:userModel.wechat_token||'',
                wxunm:userModel.wechat_nickname||'',
                reg_uuid:userModel.uuid||'',
                unionid : userModel.wechat_token_union || '',
                mobile: userModel.mobile
            };
            return retData;
    };
    //----------------------------------------------------------------
    /**
     * 转移用户文档, 从第一个用户名下转移到第二个用户名下
     * fromUser 被转移文档的用户
     * toUser   转移至 toUser 名下
     * callback 回调
     *          callbac 参数
     *              err: 错误信息
     * */
    usersUtil.moveUserDoc = function moveUserDoc(fromUser, toUser, callback) {

        // ppt 文档
        var docEnt = new ItbDocumentModel({
            user_id_from : fromUser.user_id,
            user_id_to : toUser.user_id
        });
        // 转移用户 ppt 文档
        docEnt.moveDocByUser(function(err, ret){
            if (err) {
                console.log('usersUtil.js [moveUserDoc] move Doc Err: ' + err);
                return callback(err);
            }

            // 转移用户竖屏文档
            var tgEnt = new TgUserDocModel({
                user_id_from : fromUser.user_id,
                user_id_to : toUser.user_id
            });
            tgEnt.moveDocByUser(function(err2,ret2){
                if (err2) {
                    console.log('usersUtil.js [moveUserDoc] move TgDoc Err: ' + err2);
                    return callback(err);
                }

                return callback(null);
            });
        });
    };
    //----------------------------------------------------------------
    /**
     * 合并用户,
     * 保留第一个用户(填写完整数据, 此方法内直接更新),
     * 第二个用的文档转移至第一个用户名下, 并注销第二个用户
     *
     * 参数: strongUser  主用户, 合并后保留的用户
     * 参数: weakUser    次用户, 合并后, 被转移文档, 并注销的用户
     * 参数: callback    合并用户结束回调
     *          callback 参数:
     *              err: 合并失败信息
     *              strongUser:     合并后的用户
     *
     * */
    usersUtil.combinedUser = function combinedUser(strongUser, weakUser, callback) {

        // 合并用户
        strongUser.updateToDB(function(combinedErr) {
            if (combinedErr) {
                console.log('usersUtil.js [combinedUser] update user Err:' + combinedErr);
                return callback(combinedErr, null);
            }
            // 转移用户文档(ppt 竖屏)
            usersUtil.moveUserDoc(weakUser, strongUser, function(err){
                if(err) {
                    console.log("usersUtil [combinedUser] move user doc err: ", err);
                    return callback(err, strongUser);
                }

                // 注销 weak user
                var delUser = new ItbUserModel({
                    user_id : weakUser.user_id,
                    del_flg : 1
                });
                delUser.updateToDB(function(delUserErr){
                    if(delUserErr) {
                        console.log("usersUtil [combinedUser] del user err: ", err);
                        return callback(delUserErr);
                    }
                    return callback(null, strongUser);
                });
            });
        });
    };
    //----------------------------------------------------------------
    /**
     * [废弃]web 微信登录逻辑
     * 参数:  user     ItbUserModel 包含登录传递的微信用户信息
     * 参数:  callback 微信登录回调
     *              callback 参数
     *              err: 微信登录失败
     *              loginUser: 微信登录结果
     * */
    usersUtil.webWechatLogin = function webWechatLogin(user, callback) {
        var unionEntity = new ItbUserModel({
            wechat_token_union: user.wechat_token_union,
            del_flg: 0,
        });
        unionEntity.findFromDB(function (findUserErr, items) {
            if (findUserErr) {
                console.log('usersUtil.js [webWechatLogin] find unionid user Err: ' + error);
                return callback(findUserErr);
            }
            // 查询到了用户
            if (items != null && items.length > 0) {
                // 直接返回用户信息
                return callback(findUserErr, items[0]);
            }
            // 没有查询到用户, 根据 unionid 创建用户, 并返回信息
            else {
                // 创建用户(清空 user_id)
                user.user_id = null;
                // 网站只存 unionid 不存 openid(数据库 wechat_token 字段, 仅表示 app wechat openId)
                user.wechat_token = null;
                user.saveToDB(function(createUserErr, userId){
                    // 创建用户失败
                    if(createUserErr){
                        console.log('usersUtil.js [webWechatLogin] create unionid user Err:'+saveErr);
                        return callback(createUserErr)
                    }



                    // 创建成功, 回调
                    user.user_id = userId;
                    return callback(createUserErr, user);
                });
            }
        });
    };
    //----------------------------------------------------------------
    /**
     * [废弃]app 微信登录逻辑
     *
     * 参数: user 包含登录信息的 ItbUserModel
     * 参数: callback app 登录回调
     *          callback 参数
     *              err: 登录错误回调
     *              loginUser: 登录结果
     * */
    usersUtil.appWechatLogin = function appWechatLogin(user, callback) {
        var unionUser = new ItbUserModel({
            wechat_token_union : user.wechat_token_union,
            del_flg : 0
        });

        unionUser.findFromDB(function(findUnionUserErr, unionItems){
            if(findUnionUserErr) {
               console.log("usersUtil.js [appWechatLogin] find union user err: " + findUnionUserErr);
               return callback(findUnionUserErr);
            }

            // 查询到 unionid 用户
            if( unionItems!= null && unionItems.length > 0) {
                // unionid 用户 存在 openId , 正常用户, 直接返回即可
                var union = unionItems[0];
                if(typeof union.wechat_token != 'undefined' &&
                    union.wechat_token != null &&
                    union.wechat_token.length > 0) {
                    return callback(null, union);
                }

                // union id 用户不存在 openId , 查询 openId 用户
                var openUser = new ItbUserModel({
                    wechat_token : user.wechat_token,
                    del_flg : 0
                });
                openUser.findFromDB(function(findOpenUserErr, openItems){
                    if(findOpenUserErr) {
                        console.log("usersUtil.js [appWechatLogin] find open user err: " + findOpenUserErr);
                        return callback(findOpenUserErr);
                    }
                    // 存在 openid user
                    if(openItems != null && openItems.length > 0) {
                        // 此处取得的应该是老数据, 直接绑定
                        var open = new ItbUserModel({
                            user_id : openItems[0].user_id,
                            wechat_token_union : union.wechat_token_union,
                            del_flg : 0
                        });
                        usersUtil.combinedUser(open, union, function(combinedErr, combinedUser){
                            if(combinedErr) {
                                console.log("usersUtil.js [appWechatLogin] combined user err: " + findOpenUserErr);
                                return callback(findOpenUserErr);
                            }
                            return callback(null, combinedUser);
                        });
                    }
                    // 不存在 openid user,  返回 union用户信息
                    else {
                        var updUser = new ItbUserModel({
                            user_id : union.user_id,
                            wechat_token : user.wechat_token
                        });
                        updUser.updateToDB(function(updateErr){

                            if(updateErr) {
                                console.log("usersUtil.js [appWechatLogin] update union of wechat_token err: " + updateErr);
                                return callback(updateErr);
                            }
                            // 返回合并后的用户信息
                            union.wechat_token = user.wechat_token;
                            return callback(null, union);
                        });
                    }
                });

            }
            // 没有查询到 unionid 用户
            else {
                // 查询 openid 用户
                var openUser = new ItbUserModel({
                    wechat_token : user.wechat_token,
                    del_flg : 0
                });
                openUser.findFromDB(function(findOpenUserErr, openItems){
                    if(findOpenUserErr) {
                        console.log("usersUtil.js [appWechatLogin] find open user err: " + findOpenUserErr);
                        return callback(findOpenUserErr);
                    }
                    // 存在 openid user
                    if(openItems != null && openItems.length > 0) {
                        // 更新 union id, 返回 loginUser 信息
                        var upUser = new ItbUserModel({
                            user_id : openItems[0].user_id,
                            wechat_token_union : user.wechat_token_union,
                        });
                        upUser.updateToDB(function(updateUserErr){
                            if(updateUserErr) {
                                console.log("usersUtil.js [appWechatLogin] update user err: " + updateUserErr);
                                return callback(updateUserErr);
                            }
                            // 更新成功, 返回用户信息
                            var unionUser = openItems[0];
                            unionUser.wechat_token_union = user.wechat_token_union;
                            return callback(null, unionUser);
                        });

                    }
                    // 不存在 openid user
                    else {
                        // 创建用户, 返回 loginUser 信息(清空 user_id )
                        user.user_id = null;
                        user.saveToDB(function(createUserErr, userId){

                            if(createUserErr) {
                                console.log("usersUtil.js [appWechatLogin] create user err: " + findOpenUserErr);
                                return callback(createUserErr);
                            }
                            user.user_id = userId;
                            return callback(null, user);
                        });
                    }
                });
            }
        });
    };

    //----------------------------------------------------------------
    /**
     * 绑定微信用户信息
     * 参数: user,    用户信息
     * 参数: res      响应参数, 部分错误信息在此接口直接返回
     * 参数: callback,   绑定成功回调
     *              callback 参数
     *                  err: 绑定失败
     *                  bindedUser: 绑定之后的用户
     * */
    usersUtil.bindWechat = function(user, res, callback) {
        // 先根据 unionid 查询, 再根据 openId 查询
        // 根据 unionid 查询微信用户, 查得到就绑定, 查不到, 根据 openid 查询
        var unionUser = new ItbUserModel({
            wechat_token_union : user.wechat_token_union,
            del_flg : 0
        });
        unionUser.findFromDB(function(findUnionUserErr, unionUsers) {
            if (findUnionUserErr) {
                console.log("usersUtil.js [bindWechat] find unionid user err: " + findUnionUserErr);
                return callback(findUnionUserErr);
            }
            // 有 unionid user
            if (unionUsers != null && unionUsers.length > 0) {
                // check union user
                if (unionUsers.length > 1) {
                    return usersUtil.ret_func_json(0, "该微信账号已被注册多次", null, res);
                }
                var unionUser0 = unionUsers[0];
                if (unionUser0.user_id == user.user_id) {
                    return usersUtil.ret_func_json(0, "该微信账号已经绑定当前用户", null, res);
                }
                if (unionUser0.mobile && (unionUser0.mobile + '').length > 1) {
                    return usersUtil.ret_func_json(0, "该微信账号已经绑定其它用户", null, res);
                }

                // unionid user 存在, 查询 openId user, 若存在, 则合并 openId user 和 unionid user,
                var openidUser = new ItbUserModel({
                    wechat_token: user.wechat_token,
                    del_flg: 0
                });
                openidUser.findFromDB(function (findOpenIdUserErr, openidUsers) {
                    if (findOpenIdUserErr) {
                        console.log("usersUtil.js [bindWechat] find openid user err: " + findOpenIdUserErr);
                        return  callback(findOpenIdUserErr);
                    }
                    // 存在 openId user, 合并 unionid openId user, 再绑定至 当前用户
                    if (openidUsers != null && openidUsers.length > 0) {
                        var needCombinedUser = null;
                        for(var i in  openidUsers) {
                            var tmpOpenidUser = openidUsers[i];
                            if(tmpOpenidUser.wechat_token_union != unionUser0.wechat_token_union) {
                                needCombinedUser = tmpOpenidUser;
                                break;
                            }
                        }
                        // 需要合并openId user 和 union id user用户
                        if(needCombinedUser) {
                            // 合并 unionid user 和 openid user
                           needCombinedUser = new ItbUserModel(needCombinedUser);
                            usersUtil.combinedUser(needCombinedUser, unionUser0, function (bindUserErr, wechatUser) {
                                if (bindUserErr) {
                                    console.log("usersUtil.js [bindwechat] combined openid user union id user Err: ", bindUserErr);
                                    return callback(bindUserErr);
                                }
                                // 绑定至当前账户
                                usersUtil.combinedUser(user, wechatUser, function (bindErr, bindedUser) {
                                    if (bindErr) {
                                        console.log("usersUtil.js [bindWechat] bindWechatUser err: " + bindErr);
                                        return callback(bindErr);
                                    }
                                    return callback(bindedUser, user);
                                });
                            });
                        }
                        // 不需要合并
                        else {
                            usersUtil.combinedUser(user, unionUser0, function (bindErr, bindedUser) {
                                if (bindErr) {
                                    console.log("usersUtil.js [bindWechat] bindWechatUser err: " + bindErr);
                                    return callback(bindErr);
                                }
                                return callback(bindErr, bindedUser);
                            });
                        }
                    } else {
                        // 有 unionid user, 不存在 openIdidUser 绑定 unionid user 至当前用户
                        usersUtil.combinedUser(user, unionUser0, function (bindErr, bindedUser) {
                            if (bindErr) {
                                console.log("usersUtil.js [bindWechat] bindWechatUser err: " + bindErr);
                                return callback(bindErr);
                            }
                            return callback(bindErr, bindedUser);
                        });
                    }
                });
            }
            // 没有  unionid 对应的用户, 查找 对应 openId 对应的用户
            else {
                var openidUser = new ItbUserModel({
                    wechat_token: user.wechat_token,
                    del_flg: 0
                });
                openidUser.findFromDB(function (findOpenIdUserErr, openidUsers) {
                    if (findOpenIdUserErr) {
                        console.log("users.js [bindWechat2] find openid user err: " + findOpenIdUserErr);
                        return callback(findOpenIdUserErr);
                    }
                    // 有 openId user
                    if (openidUsers != null && openidUsers.length > 0) {
                        // check openid user
                        if (openidUsers.length > 1) {
                            return usersUtil.ret_func_json(0, "该微信账号已被注册多次", null, res);
                        }
                        var openidUser0 = openidUsers[0];
                        if (openidUser0.user_id == user.user_id) {
                            return usersUtil.ret_func_json(0, "该微信账号已经绑定当前用户", null, res);
                        }
                        if (openidUser0.mobile && (openidUser0.mobile + '').length > 1) {
                            return usersUtil.ret_func_json(0, "该微信账号已经绑定其它用户", null, res);
                        }

                        // 不存在 unionid user, 但是存在 openid 用户, 绑定 openId 用户
                        return usersUtil.combinedUser(user, openidUser0, function (bindErr, bindedUser) {
                            if (bindErr) {
                                console.log("usersUtil.js [bindWechat] bindWechatUser err: " + bindErr);
                                return callback(bindErr);
                            }
                            return callback(bindErr, bindedUser);
                        });
                    }
                    // 没有 openId user, 直接绑定至当前用户
                    else {
                        // 微信号未注册过,绑定到当前用户
                        user.updateToDB(function (error) {
                            // process error
                            if (error) {
                                console.log('usersUtil.js [bindWechat] Upd Err: ' + error);
                                return callback(error);
                            }
                            return callback(null, user);
                        }); // bind wechat

                    } // no openId user
                }); // find openid user
            } // no union id user
        });
    };

    //----------------------------------------------------------------
    /**
     * 查找用户，如果不存在则创建之
     * 参数: mobile,
     * 参数: uuid
     * 参数: callback,   绑定成功回调
     *              callback 参数
     *                  err: 绑定失败
     *                  userItem: 绑定之后的用户
     * */
    usersUtil.findInsertUser=function(mobile, uuid, callback){
        // 检索user
        var entity = new ItbUserModel({
                mobile : mobile,
                user_type : 1,
                del_flg : 0
            });
        entity.findFromDB(function(error, items){
            if (error){
                return callback(error, null);
            }

            if (items != null && items.length > 0) {
                return callback(null, items[0]);

            } else {
                // 创建用户
                var DEF_PW = 'ED035DE6D7392A03642D246BC95D06A2';// DefaultFromWechatBindMobile
                var entity2 = new ItbUserModel({
                    password  : DEF_PW,// 123456
                    uuid      : uuid,
                    user_type : 1,
                    mobile    :mobile
                });
                //entity2.saveToDB(function(err, newUserId){
                entity2.insWhenMobileNotExist(function(err, newUserId){// modified by xc 2017-06-13
                    if(err){
                        console.log('usersUtil.js [insWhenMobileNotExist] create user error: '+err);
                        return callback(error, null);
                    }

                    if(newUserId && newUserId>0) {
                        // 兑换优惠券并尝试添加为下线 //todo
                        usersUtil.exchgCouponAndTryAddPartnerCustom(mobile, function () {

                            var ret = {
                                user_id:newUserId,
                                user_type:entity2.user_type,
                                mobile:entity2.mobile,
                                uuid : uuid
                            };
                            return callback(error, ret);
                        });

                    } else {
                        console.log('usersUtil.js [insWhenMobileNotExist] user Exist');
                        // 已经存在，再查找一遍
                        var entity3 = new ItbUserModel({
                            mobile : mobile,
                            del_flg : 0
                        });
                        entity3.findFromDB(function(findErr, findRet){
                            if (findErr){
                                return callback(findErr, null);
                            }
                            if (findRet && findRet.length > 0) {
                                return callback(null, findRet[0]);
                            } else {
                                return callback('用户不存在', null);
                            }
                        });
                    }
                });
            }
        });
    };

    //----------------------------------------------------------------
    /**
     * 将用户领取的优惠券进行兑换并尝试添加为合伙人的下线
     * 参数: mobile
     * 参数: callback，参数如下：
     *      error
     * */
    usersUtil.exchgCouponAndTryAddPartnerCustom = function(mobile, callback){
        if(!mobile){
            return callback("mobile is null!");
        }

        // 根据领券(state=15,expiry_time大于当前时间，draw_time时间最早)情况获取发放者id
        (new ItbCouponModel).getFirstChannelUserId(mobile, function(error, channel_u){
            if(!channel_u){
                console.log('usersUtil.exchgCouponAndTryAddPartnerCustom getFirstChannelUserId failed! '+error);
                return callback(error, null);
            }

            // 将用户领取(state=15)的优惠券进行兑换（同时处理多张）
            (new ItbCouponModel).exchgCouponOfuser(mobile, function(error){
                // 尝试添加为合伙人的下线
                usersUtil.tryAddPartnerCustom(channel_u, mobile, function(error){
                    return callback(error);
                });
            });
        });
    }

    //----------------------------------------------------------------
    /**
     * 获取用户文档
     * 参数: userId
     * 参数: typeL: 0 未分类(返回所有); 1 海报; 2 多页; 3 ppt; 4 印品
     * 参数: pageNum: 请求页号(0开始 )
     * 参数: pageSize: 请求页大小(空或0时获取所有)
     * 参数: callback
     * */
    usersUtil.get_UserDocs=function(userId,typeL,pageNum,pageSize, callback){
        (new TgUserDocModel).getUserDocsByTypeL(userId,typeL,pageNum,pageSize,callback);
    };

    /**
     * 获取用户文档个数
     * 参数: userId
     * 参数: typeL: 0 未分类(返回所有); 1 海报; 2 多页; 3 ppt; 4 印品
     * 参数: pageNum: 请求页号(0开始 )
     * 参数: pageSize: 请求页大小(空或0时获取所有)
     * 参数: callback
     * */
    // todo 新增获取数量接口, 已实现 待审核, begin
    usersUtil.get_UserDocsCnt=function(userId,typeL,pageNum,pageSize, callback){
        (new TgUserDocModel).getUserDocsByTypeLCnt(userId,typeL,callback);
    };
    // todo 新增获取数量接口, 已实现 待审核, end
    //----------------------------------------------------------------
    /**
     * 重命名用户文档
     * 参数: userId
     * 参数: typeL: 0 未分类(错误); 1 海报; 2 多页; 3 ppt; 4 印品
     * 参数: docId: 文档id
     * 参数: docName: 文档名
     * 参数: callback
     * */
    usersUtil.renameUserDoc=function(userId, typeL, docId, docName, callback){
        typeL = Number(typeL||'0');
        /**
         *
         // 1.单页  2.多页  3.ppt  4.印品  6.社交媒体  7.电商  8.微商 1010. logo 1011 营销商品
         CONFIG.DOC_TYPE_1 = 1;
         CONFIG.DOC_TYPE_2 = 2;
         CONFIG.DOC_TYPE_3 = 3;
         CONFIG.DOC_TYPE_4 = 4;
         CONFIG.DOC_TYPE_6 = 6;
         CONFIG.DOC_TYPE_7 = 7;
         CONFIG.DOC_TYPE_8 = 8;
         CONFIG.DOC_TYPE_1010 = 1010;
         CONFIG.DOC_TYPE_1011 = 1011;
         * */
        if( typeL == CONFIG.DOC_TYPE_1 ||
            typeL == CONFIG.DOC_TYPE_2 ||
            typeL == CONFIG.DOC_TYPE_4 ||
            typeL == CONFIG.DOC_TYPE_6 ||
            typeL == CONFIG.DOC_TYPE_7 ||
            typeL == CONFIG.DOC_TYPE_8 ||
            typeL == CONFIG.DOC_TYPE_1010) {
            // 安全检查
            var chkEnt = new TgUserDocModel({
                doc_id: docId,
                user_id: userId,
                del_flg: 0
            });
            chkEnt.findFromDB(function(chkErr, chkRet){
                if(chkErr) {
                   return callback(chkErr, null);
                }
                if(chkRet && chkRet.length>0) {
                    // 可更新
                    var updEnt = new TgUserDocModel({
                        doc_id: docId,
                        doc_name: docName||'',
                        update_by: userId
                    });
                    updEnt.updateToDB(function(err){
                        return callback(err, null);
                    });

                } else {
                    return callback('无法更新', null);
                }
            });

        } else if (typeL == 3) {// PPT
            // 安全检查
            var chkEnt2 = new ItbDocumentModel({
                doc_id: docId,
                user_id: userId,
                del_flg: 0
            });
            chkEnt2.findFromDB(function(chkErr2, chkRet2){
                if(chkErr2) {
                    return callback(chkErr2, null);
                }
                if(chkRet2 && chkRet2.length>0) {
                    // 可更新
                    var updEnt2 = new ItbDocumentModel({
                        doc_id: docId,
                        doc_name: docName||'',
                        update_by: userId
                    });
                    updEnt2.updateToDB(function(err2){
                        return callback(err2, null);
                    });

                } else {
                    return callback('无法更新', null);
                }
            });

        } else {
            return callback('无效分类',null);
        }
    };

    //----------------------------------------------------------------
    /* 提交设计师合作信息
     * 参数: userId	用户唯一标识
     * 参数: info	{
     *                  "organize":"武汉示界港科技有限公司",
     *                  "name":"呵呵哒","
     *                  mobile":13037148601,
     *                  "email":"123@qq.com",
     *                  "qq":123456789
     *               }
     * 参数: hourLimit 时间限制，不能插入太频繁
     * 参数: callback,参数如下：
     *              error：
     *              id:新id，失败返回null
     * */
    usersUtil.applyPartner = function(userId,info,hourLimit, callback){
        var newEnt = new ItbPartnerApplicationModel({
            user_id:userId,
            state:10        // '状态: 10新建 20审核中 30完成',
        });

        if(info.organize){
            newEnt.organize = info.organize;
        }
        if(info.name){
            newEnt.name = info.name;
        }
        if(info.mobile){
            newEnt.mobile = info.mobile;
        }
        if(info.email){
            newEnt.email = info.email;
        }
        if(info.qq){
            newEnt.qq = info.qq;
        }

        newEnt.insertPartnerInHour(hourLimit, function(error, id){
            if(error){
                console.log('usersUtils.js [applyPartner] create application Err:'+error);
                return callback(error,null);
            }

            return callback(null, id);
        });
    }


    //----------------------------------------------------------------
    /* 删除用户作品
     * 方式: GET
     * 参数：userId,用户id
     * 参数: typeL	0 未分类(错误) 1 海报  2 多页  3 ppt.  4. 印品
     * 参数: id	 作品 id
     * 参数: callback,参数如下：
     *              error：
     */
    usersUtil.removeDoc = function(userId, typeL,id, callback){
        /**
         *
         // 1.单页  2.多页  3.ppt  4.印品  6.社交媒体  7.电商  8.微商 1010. logo 1011 营销商品
         CONFIG.DOC_TYPE_1 = 1;
         CONFIG.DOC_TYPE_2 = 2;
         CONFIG.DOC_TYPE_3 = 3;
         CONFIG.DOC_TYPE_4 = 4;
         CONFIG.DOC_TYPE_6 = 6;
         CONFIG.DOC_TYPE_7 = 7;
         CONFIG.DOC_TYPE_8 = 8;
         CONFIG.DOC_TYPE_1010 = 1010;
         CONFIG.DOC_TYPE_1011 = 1011;
         * */
        if( typeL == CONFIG.DOC_TYPE_1 ||
            typeL == CONFIG.DOC_TYPE_2 ||
            typeL == CONFIG.DOC_TYPE_4 ||
            typeL == CONFIG.DOC_TYPE_6 ||
            typeL == CONFIG.DOC_TYPE_7 ||
            typeL == CONFIG.DOC_TYPE_8 ||
            typeL == CONFIG.DOC_TYPE_1010){

            (new TgUserDocModel).safeRemoveDoc(userId, id, function(error){
                return callback(error);
            });
        }else if(typeL == CONFIG.DOC_TYPE_3){
            (new ItbDocumentModel).safeRemoveDoc(userId, id, function(error){
                return callback(error);
            });
        }else{
            return callback("一级分类错误");
        }

    }


    //------------------------------------------------------------------
    /* 获取用户订单对应的印品作品预览图.
     * 参数: userId	用户唯一标识
     * 参数: orderId	 商品订单 id
     * 参数：callback：回调，参数如下：
     *          error:错误消息
     *          data: 作品数组，如下：
     *             [
     * 	              {
     * 	                "id":345,
     * 	                "detailOrderId":1,
     * 	                "previews":[
     * 	                    "http://oss-image.jpg",
     * 	                    "http://oss-image.jpg"
     * 	                ]
     * 	              }
     * 	          ]
     * */
    usersUtil.getDocPreviewByOrder = function(userId, orderId, callback){
        (new TgUserDocModel).safeGetDocPreviewByOrder(userId, orderId,function(error, data){
            if(data){
                /*   data: 数组，属性如下：
                 *                  detail_id:子订单id
                 *                  doc_id:用户文档id
                 *                  thumbs: 图，多张图以逗号拼接
                 */
                var ret = [];
                for(var i=0;i<data.length;i++){
                    var one = data[i];
                    ret.push({
                        id:one.doc_id,
                        detailOrderId:one.detail_id,
                        previews:one.thumbs.split(",")
                    });
                }
                return callback(null, ret);
            }else{
                return callback(error ,null);
            }
        });
    };

    // MD5加密（返回结果大写）
    usersUtil.doMD5=function(str){
        var tmp = crypto.createHash('md5').update(str,'utf8').digest('hex');
        tmp = tmp.toUpperCase();
        return tmp;
    };

    /**
     * 获取当前用户的环信信息
     * @param userId
     * 返回:
     * {
     *  “hxUserName":"tttt", // 用户名, 英文字母和数字, 1k 以内不支持大小写
     *  “hxPassword”:"hxttt" // 密码暂无限制
     * }
     */
    usersUtil.getUserHxInfo=function(userId, callback){
        // 获取用户信息
        (new ItbUserModel).getUserInfoWithOrgRole(userId, 1/*Itbour*/, function(err, ret){
            if(err){
                return callback(err, null);
            }

            if(ret && ret.length>0){
                // 生成用户名/密码
                var hxUserInfo = hxUtil.genHxUserInfo(userId, ret[0].role);
                var retData = {
                    hxUserName: hxUserInfo.uid,
                    hxPassword: hxUserInfo.pwd
                };

                // 已注册 并 已记录
                if(ret[0].hx_user_name && ret[0].hx_user_name == retData.hxUserName) {
                    return callback(null, retData);
                }

                // 检查环信用户
                hxUtil.getHxUser(hxUserInfo.uid, function(chkErr, chkRet) {
                    if(chkRet && chkRet.entities && chkRet.entities.length>0) {
                        // 已注册过
                        // 更新DB
                        var updEnt = new ItbUserModel({
                            user_id: userId,
                            hx_user_name: hxUserInfo.uid,
                            update_by: userId,
                        });
                        updEnt.updateToDB(function(updErr){
                            if(updErr) {
                                return callback(updErr, null);
                            }
                            return callback(null, retData);
                        });

                    } else {
                        // 注册环信用户
                        hxUtil.regHxUser(hxUserInfo.uid, hxUserInfo.pwd, function(regErr, regRet) {
                            if(regErr) {
                                return callback(regErr, null);
                            }

                            // 更新DB
                            var updEnt = new ItbUserModel({
                                user_id: userId,
                                hx_user_name: hxUserInfo.uid,
                                update_by: userId,
                            });
                            updEnt.updateToDB(function(updErr){
                                if(updErr) {
                                    return callback(updErr, null);
                                }
                                return callback(null, retData);
                            });
                        });
                    }
                });

            } else {
                return callback('未找到用户', null);
            }
        });
    };

    /**
     * 获取客服的环信id
     * @param userId
     * @param hxId
     * 返回:
     * {
     *  "serviceId": 996
     * }
     */
    usersUtil.getHxServiceId=function(userId, hxId, callback){
        (new ItbUserModel).getOrgRoleUser(1/*Itbour*/, 1024/*环信客服*/, function(err, ret){
            if(err){
                return callback(err, null);
            }

            if(ret && ret.length>0){
                var idx = Math.floor(Math.random()*(ret.length));// TODO

                var hxUserInfo = hxUtil.genHxUserInfo(ret[idx].user_id, ret[idx].role);

                return callback(null, {serviceId: hxUserInfo.uid});

            } else {
                return callback('未找到用户', null);
            }
        });
    };


    // todo 抽出工具方法, 待审核 begin
    /* 组织用户数据
     * 参数: platformRecds(包含itb_user数据的itb_platform_user数据)
     * 返回值:
     {
     "userId":1055,
     "userType":1,
     "mobile":13297922921,
     "registerUUID":"QWERTYUIOP-iOS",
     "nickName":"哈哈",
     "headUrl":"http://www.itbour.com/header/xxx.png",
     "userSign":"我就是不写签名咋地了",
     "accessory":[
     {
     "platform":1,
     "nickName":"平台一昵称",
     "headerUrl":"平台一头像",
     "field1":"平台一字段一",
     "field2":"平台一字段二",
     "field3":"平台一字段三",
     "field4":"平台一字段四",
     "field5":"平台一字段五"
     }
     ]
     }

     原方法: /routers/users.js -> initOrganizeUserInfo
     **/
    usersUtil.initOrganizeUserInfo_v5_2 = function(userItem){
        return {
            userId: userItem.user_id,
            userType: userItem.user_type,
            mobile: userItem.mobile,
            registerUUID: userItem.uuid||'',
            nickName: userItem.nickname||'',
            headerUrl: userItem.head_url||'http://itbour-back.oss-cn-hangzhou.aliyuncs.com/app/default_head.png',
            userSign: userItem.signature||'',
            accessory: []
        };
    }
    // 原方法  /routers/users.js -> organizeUserInfo

    usersUtil.organizeUserInfo_v5_2 = function(items) {
        var retData = null;

        if(items && items.length>0) {
            retData = usersUtil.initOrganizeUserInfo_v5_2(items[0]);

            for(var i=0; i<items.length; i++){
                retData.accessory.push({
                    "platform": items[i].platform,
                    "nickName": items[i].p_nickname||'',
                    "headerUrl": items[i].p_head_url||'',
                    "field1": items[i].field1||'',
                    "field2": items[i].field2||'',
                    "field3": items[i].field3||'',
                    "field4": items[i].field4||'',
                    "field5": items[i].field5||'',
                });
            }
        }

        return retData;
    }
    // todo 抽出工具方法, 待审核 end



    //----------------------------------------------------------------
    /**
     * 广播／通知 (默认会更新通知状态)
     * 参数: userId	用户唯一标识
     * 参数: timestamp 	查询[有效期]在此[时间戳]之后的活动广播 "2017-04-11 10:14:00" (19位年月日十分秒)
     * 参数: states  用户通知的状态(逗号链接字符串): "10,20"
     * 参数: callback,参数如下：
     *          error,错误
     *          data,对象：
     *                                   {
     *                                          "broadcast":[
     *                                              {
     *                                                  "title":"广播标题",
     *                                                  "message":"消息内容",
     *                                                  "url":"http://www.itbour.com",
     *                                                  "start_time":"2017-04-11 10:14:00"
     *                                              }
     *                                          ],
     *                                          "notifications":[
     *                                              {
     *                                                  "title":"系统通知",
     *                                                  "message":"感谢您的意见反馈",
     *                                                  "url":"http://www.itbour.com",
     *                                                  "start_time":"2017-04-11 12:30:01"
     *                                              }
     *                                          ]
     *                                  }
     * */
    usersUtil.getBroadcastAndNotifications=function(userId, timestamp, states, callback){
        var entity = new ItbNotificationModel();
        entity.getBroadcast(timestamp,function(error, broadcast){
            if(error){
                return callback(error, null);
            }

            broadcast = broadcast || [];

            entity.getNotifications(userId, null/*timestamp*/, states, function(error, notifications){
                if(error){
                    return callback(error, null);
                }

                notifications = notifications || [];

                if(notifications.length>0) {
                    var updIds = '';
                    for(var i=0; i<notifications.length; i++) {
                        if(i>0) updIds+=',';
                        updIds += notifications[i].r_id;
                    }

                    (new ItbNotifyUserModel).updState(userId, updIds, 20/*已获取*/, function(updErr){
                        return callback(null , {broadcast:broadcast, notifications:notifications });
                    });

                } else {
                    return callback(null , {broadcast:broadcast, notifications:[] });
                }
            });
        });
    };

    //----------------------------------------------------------------
    /**
     * 检查是否为合法城市合伙人
     * 参数:partnerUID: 合伙人userId
     * 参数:callback: true/false
     */
    usersUtil.isValidCityPartner = function(partnerUID, callback) {
        (new ItbPartnerApplicationModel).isValidCityPartner(partnerUID, function(err, chkRet){
            if(err) {
                return callback(err, null);
            }
            return callback(null, chkRet);
        });
    };

    //----------------------------------------------------------------
    /**
     * 检查指定手机号是否抽过奖
     * 参数:mobile: 手机号
     * 参数:chkDate[可选]: 指定日期(默认为今天) 格式:yyyy-mm-dd
     * 参数:callback: true/false
     */
    usersUtil.chkCouponByMobile = function(mobile, chkDate, callback) {
        var chkDateStart = null;
        var chkDateEnd = null;
        if(chkDate && chkDate.length==10) {
            chkDateStart = chkDate+' 00:00:00';
            chkDateEnd = chkDate+' 23:59:59';
        } else {
            var m = moment(new Date());
            chkDateStart = m.format('YYYY-MM-DD')+' 00:00:00';
            chkDateEnd = m.format('YYYY-MM-DD')+' 23:59:59';
        }
        (new ItbCouponModel).chkCouponByMobile(mobile, chkDateStart, chkDateEnd, function(err, chkRet){
            if(err) {
                return callback(err, null);
            }
            return callback(null, chkRet);
        });
    };
    /**
     * 检查指定用户是否抽过奖
     * 参数:userId: 手机号
     * 参数:chkDate[可选]: 指定日期(默认为今天) 格式:yyyy-mm-dd
     * 参数:callback: true/false
     */
    usersUtil.chkCouponByUserId = function(userId, chkDate, callback) {
        var chkDateStart = null;
        var chkDateEnd = null;
        if(chkDate && chkDate.length==10) {
            chkDateStart = chkDate+' 00:00:00';
            chkDateEnd = chkDate+' 23:59:59';
        } else {
            var m = moment(new Date());
            chkDateStart = m.format('YYYY-MM-DD')+' 00:00:00';
            chkDateEnd = m.format('YYYY-MM-DD')+' 23:59:59';
        }
        (new ItbCouponModel).chkCouponByUserId(userId, chkDateStart, chkDateEnd, function(err, chkRet){
            if(err) {
                return callback(err, null);
            }
            return callback(null, chkRet);
        });
    };

    //----------------------------------------------------------------
    /**
     * 批量领取＋兑换
     * 参数 partnerUID: 合伙人用户id
     * 参数 mobile: 抽奖人手机号
     * 参数 codes: 优惠码(数组)
     * 返回 callback
     * */
    usersUtil.getPartnerCoupons_v5_4 = function(partnerUID, mobile, codes, callback) {
        var strCodes = '';
        if(codes || codes.length>0) {
            for(var i=0; i<codes.length; i++) {
                if(i>0) {
                    strCodes += ',';
                }
                strCodes += '"'+codes[i]+'"';
            }
        } else {
            return callback('参数错误', null);
        }

        // 兑换优惠券（未注册则标记成领用状态，已注册则标记成已兑换（并更新user_id））
        (new ItbCouponModel).bindUserFromPartner(partnerUID, mobile, strCodes, function(updErr, updRet){
            if(updErr) {
                return callback(updErr, null);
            }

            // 获取优惠券详细信息
            (new ItbCouponModel).getCouponInfoByCodes(strCodes, function(getErr, getRet){
                if(getErr) {
                    return callback(getErr, null);
                }

                var retData = [];
                if(getRet && getRet.length>0) {
                    for(var i=0; i<getRet.length; i++) {
                        retData.push({
                            id: getRet[i].c_id,
                            code: getRet[i].c_code,
                            type_desc: getRet[i].type_name,
                            discount: getRet[i].discount,
                            discount_desc: (getRet[i].discount/100) +'元',
                            trade_type: getRet[i].trade_type,
                            expiry_time: getRet[i].expiry_time,
                            coupon_desc: "暂不抵扣运费",
                            expiry_flg: getRet[i].expiry_flg,
                            reason: (getRet[i].expiry_flg==1)?'已过期':'',
                            limit_type:getRet[i].top_limit_type
                        });
                    }
                }
                return callback(null, retData);
            });
        });
    };

    //----------------------------------------------------------------
    /**
     * 尝试着将手机用户对应的user加为合伙人的下线
     * 参数 partnerUID: 合伙人用户id
     * 参数 mobile: 抽奖人手机号
     * 参数 callback，返回参数：
     *          error:
     *          pc_id:下线纪录的id
     * */
    usersUtil.tryAddPartnerCustom = function(partnerUID, mobile,  callback) {
        /*
        * 规则： 1、下线必须是注册用户（即mobile对应的有user id）
        *       2、合伙人之间不能成为下线
        *       3、如果用户A领取了多个合伙人的优惠券，则按A成为最早的优惠券的合伙人的下线
        *       4、一个下线只能属于一个合伙人，不能属于多个合伙人
        * */
        usersUtil.checkPartnerCustomCondition( partnerUID, mobile, function (error, success) {
            if(success){
                usersUtil.addPartnerCustom( partnerUID, mobile, function (error, pc_id) {
                    if(error){
                        return callback(error, null);
                    }else{
                        return callback(null, pc_id);
                    }
                });
            }else{
                return callback(error,null);
            }
        });
    }
    //----------------------------------------------------------------
    /**
     * 检测手机用户是否能成为为合伙人的下线
     * 参数 partnerUID: 合伙人用户id
     * 参数 mobile: 抽奖人手机号
     * 返回 callback，参数如下：
     *          error
     *          success:1表示检测通过
     * */
    usersUtil.checkPartnerCustomCondition = function(partnerUID, mobile,  callback) {
        /*
         * 规则： 1、下线必须是注册用户（即mobile对应的有user id）
         *       2、合伙人之间不能成为下线
         *       3、一个下线只能属于一个合伙人，不能属于多个合伙人
         *       4、如果用户A领取了多个合伙人的优惠券，则按A成为最早的优惠券的合伙人的下线
         * */
        (new ItbPartnerModel).checkPartnerCustomCondition(partnerUID, mobile,  callback);
    }
    //----------------------------------------------------------------
    /**
     * 将用户对应的user加为合伙人的下线
     * 参数 partnerUID: 合伙人用户id
     * 参数 mobile: 抽奖人手机号
     * 返回 callback，返回参数：
     *          error:
     *          pc_id:下线纪录的id
     * */
    usersUtil.addPartnerCustom = function(partnerUID, mobile,  callback) {
        var newEnt = new ItbPartnerCustModel({
        });
        newEnt.addPartnerCustom(partnerUID, mobile, function(error, pc_id){
            if(error){
                console.log('usersUtils.js [addPartnerCustom] create user Err:'+error);
                return callback(error,null);
            }

            return callback(null, pc_id);
        });
    }

    //----------------------------------------------------------------
    /**
     * 获取用户收藏列表
     * 参数 userId: 用户唯一标识
     * 参数 pageNum: 分页页码
     * 参数 pageSize: 分页大小
     * 返回 callback
     *          err: 错误
     *          list: 收藏列表
     * */
    // todo 新增接口, 已完成, 待审核 begin
    usersUtil.get_userCollectList_v5_4 = function(userId, pageNum, pageSize, callback) {
        (new ItbCollectModel).getUserCollectList(userId, pageNum, pageSize, callback);
    };
    //----------------------------------------------------------------
    /**
     * 获取用户收藏项目个数
     * 参数 userId: 用户唯一标识
     * 参数 callback
     *          err: 错误
     *          count: 收藏项目个数
     * */
    usersUtil.get_userCollectListCnt_v5_4 = function(userId, callback) {
        (new ItbCollectModel).getUserCollectListCnt(userId, callback);
    };

    //----------------------------------------------------------------
    /**
     * 确认用户收藏项目的合法性
     * 参数 typeL : 一级分类
     * 参数 id : 收藏项的唯一标识
     * */

    usersUtil.chk_userCollectItemValid_v5_4 = function(typeL, userId, id, callback) {
        (new ItbCollectModel).checkCollectItemState(typeL, userId, id, callback);
    };
    //----------------------------------------------------------------
    /**
     * 插入收藏项目
     * 参数 typeL: 一级分类
     * 参数 userId: 用户唯一标识
     * 参数 tmpl_id: 模板唯一标识
     * 参数 item_id: 商品唯一标识, 若不存在传递 null
     * 参数 callback: 插入回调
     * */
    usersUtil.insertUserCollect_v5_4 = function(typeL, userId, tmpl_id, item_id, callback) {
        (new ItbCollectModel).userCollectItem(typeL, userId, tmpl_id, item_id, callback);
    };

    /**
     * 移除收藏项目
     * 参数 typeL: 一级分类
     * 参数 userId: 用户唯一标识
     * 参数 id: 对应分类的标识
     * 参数 callback: 回调
     * */
    usersUtil.removeUserCollect_v5_4 = function(typeL, userId, id, callback) {
        (new ItbCollectModel).removeUserCollect(typeL, userId, id, callback);
    };

    //------------------------------------------------------------------------
    /**
     * 获取城市合伙人状态信息
     * 参数 userId: 用户唯一标识
     * 参数 callback: 回调
     * */
    usersUtil.getCityPartnerInfo_v5_4 = function(userId, callback){
        (new ItbPartnerApplicationModel).getPartnerState(userId,callback);
    }


    //获取合伙人相关信息
    usersUtil.getCityPartnermessage_v5_4 =function(userId,callback){
        (new ItbPartnerModel).getPartnermessage(userId,callback);
    }

    //----------------------------------------------------------------
    /**
     * 获取城市合伙人状态信息
     * 参数 userId: 用户唯一标识
     * 参数 callback: 回调
     * */
    usersUtil.getCityPartnerInfoEx_v5_4 = function(userId, callback){
        (new ItbPartnerApplicationModel).getCityPartnerInfoEx_v5_4(userId,function(error, data){
            if(error){
                return callback(error, null);
            }
            if(data){
                data.cityInfo = {
                    prov:{id:data.prov, text:data.prov_text},
                    city:{id:data.city, text:data.city_text},
                    dist:{id:data.dist, text:data.dist_text},
                    detail:data.detail
                }
                delete data.prov;
                delete data.city;
                delete data.dist;
                delete data.prov_text;
                delete data.city_text;
                delete data.dist_text;
                delete data.detail;

                return callback(null, data);
            }
            return callback(null,null);
        });
    }
    //----------------------------------------------------------------
    /**
     * 更新合伙人状态信息
     * 参数 userId
     * 参数 info
     * 参数 callback: 回调
     * */
    usersUtil.updateCityPartnerInfo_v5_4 =function(userId, info, callback){
        (new ItbPartnerApplicationModel).updateCityPartnerInfo_0_v5_4(userId,info, function(error){
            if(error){
                return callback(error);
            }
            (new ItbPartnerApplicationModel).updateCityPartnerInfo_1_v5_4(userId,info, function(error){
                if(error){
                    return callback(error);
                }
                return callback(null);
            });
        });

    };

    //----------------------------------------------------------------
    /**
     * 获取城市合伙人收益列表
     * 参数 userId: 用户唯一标识
     * 参数 pageNum: 分页页码
     * 参数 pageSize: 分页大小
     * 参数 callback: 回调
     * */
    usersUtil.get_partnerIncome_v5_4 = function(userId, pageNum, pageSize,withTotalPage, callback) {
        var entity = new ItbPartnerIncomeModel();
        //获取合伙人收益列表
        entity.getPartnerIncomeList(userId, pageNum, pageSize, function(error,list){
            if(error){
                return callback(error, null);
            }
            var list = list || [];
            //获取合伙人总收益
            entity.getPartnerTotalIncome(userId, function(error1,totalIncome){
                if(error1){
                    return callback(error1, null);
                }
                var totalIncome = totalIncome[0].sum || 0;
                //判断是否需要传入总页数
                if(withTotalPage){
                    entity.getPartnerIncomeListCnt(userId, function(error2,totalPage){
                        if(error2){
                            return callback(error2, null);
                        }
                        var totalPage = Math.ceil(totalPage/pageSize);
                        return callback(null,{
                            "list":list,
                            totalPage :totalPage,
                            totalIncome : totalIncome,
                        })
                    })
                }else{
                    return callback(null,{
                        "list":list,
                        totalIncome : totalIncome,
                    })
                }
            })
        });
    };

    //----------------------------------------------------------------
    /**
     * 获取城市合伙人收益项目总个数
     * 参数 userId: 用户唯一标识
     * 参数 callback: 回调
     * */
    usersUtil.get_partnerIncomeCnt_v5_4 = function(userId, callback) {
        (new ItbPartnerIncomeModel).getPartnerIncomeListCnt(userId, callback);
    };

    //----------------------------------------------------------------
    /**
     * 提交城市合伙人申请
     * 参数 userId: 用户唯一标识
     * 参数 callback: 回调
     * */
    usersUtil.commit_cityPartnerInfo_v5_4 = function(userId,info,hourLimit,p_userId,callback) {
        var newEnt = new ItbPartnerApplicationModel({
                user_id:userId,
                type:20,
                state:10,
        });
        //将info信息传入到对象中
        if(info.name){
            newEnt.name = info.name;
        }
        if(info.level){
            newEnt.level = info.level;
        }else{
            newEnt.level = 10;
        }
        if(info.cityInfo.prov.id){
            newEnt.prov = info.cityInfo.prov.id;
        }
        if(info.cityInfo.city.id){
            newEnt.city = info.cityInfo.city.id;
        }
        if(info.cityInfo.dist.id){
            newEnt.dist = info.cityInfo.dist.id;
        }
        if(info.cityInfo.detail){
            newEnt.detail = info.cityInfo.detail;
        }
        if(info.bank){
            newEnt.bank = info.bank;
        }
        if(info.bankAccount){
            newEnt.bank_account = info.bankAccount;
        }
        //城市合伙人的userId
        if(p_userId){
            newEnt.channel_u = p_userId;
        }
        //获取城市合伙人的状态
        newEnt.getPartnerState(userId, function(error, result){
            if(error){
                console.log('usersUtils.js [commit_cityPartnerInfo_v5_4] create application Err:'+error);
                return callback(error,null);
            }
            //如果没有申请过,创建申请提交
            if(result.length == 0){
                newEnt.insertPartnerInHour(hourLimit, function(error, result){
                    if(error){
                        console.log('usersUtils.js [applyPartner] create application Err:'+error);
                        return callback(error,null);
                    }

                    return callback(null, result);
                });
            }else{
                var state = result[0].state;
                if(state == 30){
                    newEnt.SetDel_flgIs_1(userId,function(error, result){
                        if(error){
                            console.log('usersUtils.js [SetDel_flgIs_1]  Err:'+error);
                            return callback(error,null);
                        }
                        newEnt.insertPartnerInHour(hourLimit, function(error, result01){
                            if(error){
                                console.log('usersUtils.js [applyPartner] create application Err:'+error);
                                return callback(error,null);
                            }

                            return callback(null, result);
                        });

                    })
                } else{
                    return callback(error,result);
                }
            }


        })
    };
    //----------------------------------------------------------------
    /* 提交设计师合作信息
     * 参数: userId	用户唯一标识
     * 参数: info	{
     *                  "organize":"武汉示界港科技有限公司",
     *                  "name":"呵呵哒","
     *                  mobile":13037148601,
     *                  "email":"123@qq.com",
     *                  "qq":123456789
     *               }
     * 参数: hourLimit 时间限制，不能插入太频繁
     * 参数: callback,参数如下：
     *              error：
     *              id:新id，失败返回null
     * */
    usersUtil.applyPartner = function(userId,info,hourLimit, callback){
        var newEnt = new ItbPartnerApplicationModel({
            user_id:userId,
            state:10        // '状态: 10新建 20审核中 30完成',
        });

        if(info.organize){
            newEnt.organize = info.organize;
        }
        if(info.name){
            newEnt.name = info.name;
        }
        if(info.mobile){
            newEnt.mobile = info.mobile;
        }
        if(info.email){
            newEnt.email = info.email;
        }
        if(info.qq){
            newEnt.qq = info.qq;
        }

        newEnt.insertPartnerInHour(hourLimit, function(error, id){
            if(error){
                console.log('usersUtils.js [applyPartner] create application Err:'+error);
                return callback(error,null);
            }

            return callback(null, id);
        });
    }
    //----------------------------------------------------------------
    /**
     * 查看领券用户
     * 参数 userId: 用户唯一标识
     * 参数 pageNum: 分页页码
     * 参数 pageSize: 分页大小
     * 参数 withTotalPage: 1表示返回总页数
     * 参数 callback: 回调，返回：
     *      error：
     *      data：
     *            {
     *                    "list":[
     *                            {
     *                                    "time":"04-23",
     *                                    "mobile":"133****2222",
     *                                    "couponState":1, // 优惠券状态
     *                                    "orderState":0 // 订单状态
     *                            }
     *                    ],
     *                    "pageNum":0,
     *                    "totalPage":1
     *            }
     *
     * */
    usersUtil.getPartnerCouponUsers_v5_4 = function(userId, pageNum, pageSize, withTotalPage, callback){
        var entity = new ItbCouponModel();
        entity.getPartnerCouponUsers_v5_4(userId, pageNum, pageSize, function(error, list){
            if(error){
                return callback(error, null);
            }
            //  将电话号码隐藏掉
            for(var i=0;i<list.length;i++){
                var one=list[i];
                if(one.mobile ){
                    one.mobile +="";
                    one.mobile = one.mobile.substr(0,3)+'****'+one.mobile.substr(7);
                }
            }

            // 获取总页数
            if(withTotalPage){
                entity.getPartnerCouponUsersCnt_v5_4(userId, pageNum, pageSize, function(error, count){
                    if(error){
                        return callback(error, null);
                    }
                    var totalPage = Math.floor((count-1)/pageSize)+1;
                    return callback(null, {
                        list:list,
                        pageNum:pageNum,
                        totalPage:totalPage
                    })
                });
            }else{
                return callback(null, {
                    list:list,
                    pageNum:pageNum,
                    totalPage:0
                })
            }

        });
    };

    //----------------------------------------------------------------
    /**
     * 查询合伙人订单列表
     * 参数 userId: 用户唯一标识
     * 参数 pageNum: 分页页码
     * 参数 pageSize: 分页大小
     * 参数 withTotalPage: 1表示返回总页数
     * 参数 callback: 回调，返回：
     *      error：
     *      data：
     *            {
     *                    "list":[
     *                            {
     *                                     "orderId": 456,
     *                                     "time": "2017-05-03",
     *                                     "mobile": "188****4928",
     *                                     "orderAmount": 68,
     *                                     "orderIncome": 20
     *                            }
     *                    ],
     *                    "pageNum":0,
     *                    "totalPage":1
     *            }
     *
     * */
    usersUtil.PARTNER_NORMAL_INCOME_RATE = 0.1; // 普通合伙人的分成比例
    usersUtil.getIncomeOrderList_v5_4 = function(userId, startDt, endDt, pageNum, pageSize, withTotalPage, callback){
        var entity = new ItbCouponModel();
        entity.getIncomeOrderList_v5_4(userId, startDt, endDt, pageNum, pageSize, function(error, list){
            if(error){
                return callback(error, null);
            }
            //  将电话号码隐藏掉
            for(var i=0;i<list.length;i++){
                var one=list[i];
                if(one.mobile ){
                    one.mobile +="";
                    one.mobile = one.mobile.substr(0,3)+'****'+one.mobile.substr(7)
                }
                //if(one.orderAmount){
                //    one.orderIncome = (one.orderAmount* usersUtil.PARTNER_NORMAL_INCOME_RATE).toFixed(2);
                //}else{
                //    one.orderIncome = 0;
                //}
            }

            // 获取总页数
            if(withTotalPage){
                entity.getIncomeOrderListCnt_v5_4(userId, pageNum, pageSize, function(error, count){
                    if(error){
                        return callback(error, null);
                    }
                    var totalPage = Math.floor((count-1)/pageSize)+1;
                    return callback(null, {
                        list:list,
                        pageNum:pageNum,
                        totalPage:totalPage
                    })
                });
            }else{
                return callback(null, {
                    list:list,
                    pageNum:pageNum,
                    totalPage:0
                })
            }

        });

    };

    // 获取高级城市合伙人管辖区域列表
    usersUtil.getCityPartnerAreaList_v5_6 = function(userId, callback){
        (new ItbPartnerAreaModel).getAreaListByUserId(userId, function(err, ret){
            if(err) {
                return callback(err, null);
            }

            var retData = [];
            if(ret && ret.length>0){
                for(var i=0; i<ret.length; i++) {
                    retData.push({
                        paId: ret[i].pa_id,
                        prov:{
                            id:ret[i].prov,
                            text:ret[i].prov_name
                        },
                        city:{
                            id:ret[i].city,
                            text:ret[i].city_name
                        },
                        dist:{
                            id:ret[i].dist,
                            text:ret[i].dist_name
                        },
                    });
                }
            }
            return callback(null, retData);
        });
    };

    //----------------------------------------------------------------
    usersUtil.getFirstDay = function(y,m) {
        var m = moment(new Date(y,m-1,1));
        return  m.format('YYYY-MM-DD');
    };
    usersUtil.getLastDay = function(y,m) {
        var dt = new Date(y,m,1);
        var m = moment(new Date(dt.getTime()-1000*3600*24));
        return  m.format('YYYY-MM-DD');
    };

    //----------------------------------------------------------------
    /**
     * 获取高级合伙人所选区域的所选时间段内该区域对应的订单的合伙人抽成列表
     * @param userId: 高级合伙人id
     * @param areaInfo: {"prov":150000, "city":150500, "dist":150522}
     * @param timeInfo: {"year":2017, "month":6}
     * @param pageNum
     * @param pageSize
     * @param withTotalPage
     * @param callback
     */
    usersUtil.getHighCityPartnerExIncome_v5_6 = function(userId, areaInfo, timeInfo,
        pageNum, pageSize, withTotalPage, callback){

        var stTime = null;
        var edTime = null;
        if(timeInfo && timeInfo.year>0 && timeInfo.month>0) {
            stTime = usersUtil.getFirstDay(timeInfo.year, timeInfo.month) + ' 00:00:00';
            edTime = usersUtil.getLastDay(timeInfo.year, timeInfo.month) + ' 23:59:59';
        }

        var ent = new ItbPartnerModel;
        // 按合伙人分组取子合计信息
        ent.getHighPartnerExIncome(userId, areaInfo, stTime, edTime, pageNum, pageSize, function(err, partnerSumInfo){
            if(err) {
                return callback(err, null);
            }

            // 取总体合计信息
            ent.getHighPartnerExIncomeTotal(userId, areaInfo, stTime, edTime, function(err2, totalInfo){
                if(err2) {
                    return callback(err2, null);
                }

                var retData = {
                    total:{
                        orderSum:0,
                        incomeSum:0
                    },
                    list:[]
                };

                if(totalInfo) {
                    retData.total.orderSum = Number(totalInfo.sum_total_fee||'0')||0;
                    retData.total.incomeSum = Number(totalInfo.sum_income||'0')||0;
                }

                if(partnerSumInfo && partnerSumInfo.length>0) {
                    for(var i=0; i<partnerSumInfo.length; i++) {
                        var mobile = partnerSumInfo[i].mobile+'';
                        if(Number(partnerSumInfo[i].self||'0')==0 && mobile && mobile.length>0){
                            mobile = mobile.substr(0,3)+'****'+mobile.substr(7);
                        }
                        retData.list.push({
                            partnerId: partnerSumInfo[i].partner_id,
                            mobile: mobile,
                            incomeSum: Number(partnerSumInfo[i].sum_income||'0')||0,
                            orderSum: Number(partnerSumInfo[i].sum_total_fee||'0')||0,
                            areaInfo: {
                                prov:{id: partnerSumInfo[i].prov, text: partnerSumInfo[i].prov_name},
                                city:{id: partnerSumInfo[i].city, text: partnerSumInfo[i].city_name},
                                dist:{id: partnerSumInfo[i].dist, text: partnerSumInfo[i].dist_name},
                            }
                        });
                    }
                }

                if(withTotalPage) {
                    ent.getHighPartnerExIncomeCnt(userId, areaInfo, stTime, edTime, function(err3, cnt){
                        if(err3) {
                            return callback(err3, null);
                        }

                        retData.pageNum = pageNum;
                        retData.totalPage = Math.ceil(cnt/pageSize);
                        return callback(null, retData);
                    });

                } else {
                    retData.pageNum = pageNum;
                    return callback(null, retData);
                }
            });
        });
    };

    //----------------------------------------------------------------
    /**
     * 获取城市合伙人某区域内某时间段内成单明细(额外收益)
     * @param userId: 高级合伙人id
     * @param partnerId: 指定的其它合伙人id
     * @param areaInfo: {"prov":150000, "city":150500, "dist":150522}
     * @param timeInfo: {"year":2017, "month":6}
     * @param pageNum
     * @param pageSize
     * @param withTotalPage
     * @param callback
     */
    usersUtil.getHighCityPartnerExIncomeDetail_v5_6 = function(userId, partnerId, areaInfo, timeInfo,
       pageNum, pageSize, withTotalPage, callback){

        var stTime = null;
        var edTime = null;
        if(timeInfo && timeInfo.year>0 && timeInfo.month>0) {
            stTime = usersUtil.getFirstDay(timeInfo.year, timeInfo.month) + ' 00:00:00';
            edTime = usersUtil.getLastDay(timeInfo.year, timeInfo.month) + ' 23:59:59';
        }

        var ent = new ItbPartnerModel;
        ent.getHighPartnerExIncomeDetail(userId, partnerId, areaInfo, stTime, edTime, pageNum, pageSize, function(err, ret){
            if(err) {
                return callback(err, null);
            }

            var retData = [];
            if(ret && ret.length>0) {
                for(var i=0; i<ret.length; i++) {
                    var mobile = ret[i].mobile+'';
                    if(mobile && mobile.length>0){
                        mobile = mobile.substr(0,3)+'****'+mobile.substr(7);
                    }
                    retData.push({
                        orderId: ret[i].order_id,
                        income: Number(ret[i].income||'0')||0,
                        mobile: mobile,
                        orderFee: Number(ret[i].total_fee||'0')||0,
                        time: ret[i].finish_time,
                    });
                }
            }

            if(withTotalPage) {
                ent.getHighPartnerExIncomeDetailCnt(userId, partnerId, areaInfo, stTime, edTime, function(err2, cnt){
                    if(err2) {
                        return callback(err2, null);
                    }

                    return callback(null, {
                        list: retData,
                        pageNum: pageNum,
                        totalPage: Math.ceil(cnt/pageSize),
                    });
                });

            } else {
                return callback(null, {
                    list: retData,
                    pageNum: pageNum,
                });
            }
        });
    };

    // 获取用户地址列表
    usersUtil.getUserAddressList_v5_7=function(userId, pageNum, pageSize, callback) {
        var ent = new ItbAddressModel;
        // 取type＝1的数据
        ent.getAddrListByUserId(userId, pageNum, pageSize, function(err, results){
            if(err) {
                return callback(err, null);
            }

            var retData = {list:[], pageNum:pageNum, totalPage:0};
            if(results && results.length>0) {
                for(var i=0; i<results.length; i++) {
                    retData.list.push({
                        id: results[i].addr_id,
                        mobile: results[i].mobile,
                        name: results[i].name,
                        prov: {
                            id: results[i].prov,
                            text: results[i].prov_name
                        },
                        city: {
                            id: results[i].city,
                            text: results[i].city_name
                        },
                        dist: {
                            id: results[i].dist,
                            text: results[i].dist_name
                        },
                        detail: results[i].detail,
                        default: results[i].default,
                    });
                }

                // 取count
                ent.getAddrListByUserIdCnt(userId, function(err2, cnt) {
                    if (err2) {
                        return callback(err2, null);
                    }

                    retData.totalPage = Math.ceil(cnt/pageSize);
                    return callback(null, retData);
                });

            } else {
                // 取type=0的最新一条
                //ent.getLastAddressByUserId(userId, function(err3, ret) {
                //    if(err3) {
                //        return callback(err3, null);
                //    }
                //
                //    if(ret) {
                //        retData.list.push({
                //            id: ret.addr_id,
                //            mobile: ret.mobile,
                //            name: ret.name,
                //            prov: {
                //                id: ret.prov,
                //                text: ret.prov_name
                //            },
                //            city: {
                //                id: ret.city,
                //                text: ret.city_name
                //            },
                //            city: {
                //                id: ret.city,
                //                text: ret.city_name
                //            },
                //            detail: ret.detail,
                //            default: ret.default,
                //        });
                //        retData.pageNum = 0;
                //        retData.totalPage = 1;
                //    } else {
                //        retData.pageNum = 0;
                //        retData.totalPage = 0;
                //    }

                    return callback(null, retData);
                //});
            }
        });
    };

    /**
     * 确认地址 id 数组中是否存在地址列表中的默认地址
     *
     * @param userId 用户唯一标识
     * @param ids 要查询的地址 id 集合, 用逗号拼接, 如: 123,321, 若为 null, 则查询用户的所有地址
     * @param callback 结果回调
     *              error 如果查询出错, 则为错误原因, 否为为 null
     *              id 如果查询结果有默认地址, 则为默认地址 id, 否则为 null
     * */
    usersUtil.checkUserDefaultAddress = function (userId, ids, callback) {
        ids = ids.join(',');
        (new ItbAddressModel).checkUserDefaultAddress(userId, ids, callback);
    };


    /**
     * 删除用户地址
     * @param userId 用户唯一标识
     * @param ids 有效地址数组, 如: [321, 786]
     * @param callback 回调
     * */
    usersUtil.removeUserAddress_v5_7 = function(userId, ids, callback) {

        ids = ids.join(',');
        (new ItbAddressModel).removeUserAddress_v5_7(userId, ids, callback);
    };

    /**
     * 设置用户的最新一条地址为默认地址
     *
     * @param userId 用户唯一标识
     * @param callback 回调
     *
     * 注意: 用户当前地址列表存在默认地址, 则放弃设置
     * */
    usersUtil.setUserLastAddressToDefault = function (userId, callback) {
        (new ItbAddressModel).setUserLastAddressToDefault(userId, callback);
    };

    /**
     * 设置用户某地址默认标记
     *
     * @param userId 用户唯一标识
     * @param addressId 地址唯一标识
     * @param isDefault 要设置的 default 状态, 0/1, 0 标记不设置为默认地址, 1 标识设置为默认地址
     * @param callback 回调
     *             error 设置结果是否失败
     *
     * 注意: 若 isDefault 传递为1, 设置为默认地址, 则此处将先取消原默认地址的状态, 然后再设置当前地址为默认地址
     * */
    usersUtil.setUserAddressDefault_v5_7 = function (userId, addressId, isDefault, callback) {
        // 设置 default 为 0
        if(!isDefault) {
            // 设置当前地址为默认地址
            var address = new ItbAddressModel({
                'addr_id' : addressId,
                'default' : isDefault
            });
            address.updateToDB(callback);
            return;
        }

        // 1. 取消原默认地址状态
        (new ItbAddressModel).setUserDefaultAddressToNormal(userId, function(error){
            if(error) {
                return callback(error);
            }
            // 2. 设置当前地址为默认地址
            var address = new ItbAddressModel({
                'addr_id' : addressId,
                'default' : isDefault
            });
            address.updateToDB(callback);
        });
    };

    //-------------------------------------------------------------------
    /**
     * 获取用户结算时使用的地址 id
     *
     * @param userId 用户唯一标识
     * @param addressId 初始地址 id, 若此 id 有效, 则此函数立即回调, 并传递该地址 id
     * @param callback 回调
     *              error 若获取失败, 此为错误原因
     *              addressId 查询到最合适的地址 id, 若用户当前不存在地址, 返回 0
     *
     * */
    usersUtil.getUserAddressIdForSettlement_v5_7 = function (userId, addressId, callback) {

        if(addressId && addressId >0) {
            return callback(null, addressId);
        }

        addressId = 0;
        // 1. 获取用户默认地址
        var address = new ItbAddressModel({
            user_id : userId,
            type : 1,
            default : 1,
            del_flg : 0
        });
        address.findFromDB(function(defErr, result){
            if(defErr) {
                return callback(defErr, addressId);
            }

            // 找到默认地址, 则返回默认地址 id
            if(result && result.length > 0) {
                return callback(null, result[0].addr_id);
            }

            // 没有默认地址, 获取最新地址
            usersUtil.getUserAddressList_v5_7(userId, 0, 1, function(lastErr, result1){

                if(lastErr) {
                    return callback(lastErr, 0);
                }
                if(result1 && result1.length >0) {
                    return callback(null, result1[0].addr_id);
                }
                // 最新地址也没有
                return callback(null, addressId);
            });

        }, 0, 1);
    };

    // 获取用户预填信息内容
    usersUtil.getUserDatumInfo_v6_0 = function(userId, type, callback) {
        // 获取模版信息
        var dtEnt = new ItbDatumTmplModel;
        dtEnt.getInfoByType(type, function(getErr, getRet) {
            if(getErr) {
                return callback(getErr, null);
            }

            if(getRet && getRet.length>0) {
                var tmplInfo = getRet[0];
                if(!tmplInfo.data) {
                    return callback('数据错误', null);
                }
                var tmplData = JSON.parse(tmplInfo.data);

                // 解析模版提纲树
                var tmplTgTree = null;
                //if(tmplData.version==3){
                tmplTgTree = new SJGTGV3();
                tmplTgTree.fromJson(tmplData,tmplData.version);
                //}

                // 获取用户数据
                var diEnt = new ItbDatumInfoModel;
                diEnt.getInfoByType(userId, type, function(getErr2, getRet2){
                    if(getErr2) {
                        return callback(getErr2, null);
                    }

                    if(getRet2 && getRet2.length>0) {
                        var userInfo = getRet2[0];
                        if(!userInfo || !userInfo.data || userInfo.data.length==0) {
                            return callback('数据错误', null);
                        }
                        var userData=null;
                        try{
                            userData = JSON.parse(userInfo.data);
                        }catch(e){
                            return callback('数据错误', null);
                        }
                        if(!userData){
                            return callback('数据错误', null);
                        }


                        // 解析用户数据提纲树

                        var userTgTree = null;
                        //if(tmplData.version==3){
                        userTgTree = new SJGTGV3();
                        userTgTree.fromJson(userData,userData.version);
                        //}

                        if(userInfo.ver==tmplInfo.ver && userInfo.upd_cnt==tmplInfo.upd_cnt) {
                            // 版本未升级时, 直接返回用户数据
                            return callback(null, {
                                autoFill: userInfo.auto_fill||0,
                                tmplFlg: 0,
                                datum: userData||{},
                                version: userInfo.ver||0,
                                updCnt: userInfo.upd_cnt||0,
                                dtId : tmplInfo.dt_id
                            });

                        } else {
                            // 版本不一致时, 以模版提纲为基础, 将旧用户数据填入
                            for(var i=0; i<tmplTgTree.root.children.length; i++){
                                // 暂时只支持一层结构
                                var tmplNode = tmplTgTree.root.children[i];
                                if(tmplNode){
                                    // 根据id查找对应节点的用户数据
                                    var userNode = userTgTree.root.getNodeById(tmplNode.id);
                                    if(userNode && userNode.type==tmplNode.type) {// type: 1文字/2图片
                                        if(userNode.value && tmplNode.value) {
                                            userNode.value.max = tmplNode.value.max;
                                        }
                                        tmplNode.value=userNode.value;
                                    }
                                }
                            }

                            var newData = tmplTgTree.toJson();

                            // 更新db用户数据
                            diEnt.info_id = userInfo.info_id;
                            diEnt.update_by = userInfo.user_id;
                            diEnt.data = newData||'';
                            diEnt.ver = tmplInfo.ver;// 以模版为基础
                            diEnt.upd_cnt = tmplInfo.upd_cnt;// 以模版为基础

                            diEnt.updateToDB(function(updErr){
                                return callback(updErr, {
                                    autoFill: userInfo.auto_fill||0,
                                    tmplFlg: 0,
                                    datum: JSON.parse(newData||'{}'),
                                    version: tmplInfo.ver||0,
                                    updCnt: tmplInfo.upd_cnt||0,
                                    dtId : tmplInfo.dt_id
                                });
                            });
                        }

                    } else {
                        // 返回模版数据
                        return callback(null, {
                            autoFill: 0,
                            tmplFlg: 1,
                            datum: tmplData||{},
                            version: tmplInfo.ver||0,
                            updCnt: tmplInfo.upd_cnt||0,
                            dtId : tmplInfo.dt_id
                        });
                    }
                });

            } else {
                return callback('未获取到模版信息', null);
            }
        });
    };

    // 更新用户预填信息内容
    usersUtil.updUserDatumInfo_v6_0 = function(userId, type, datum, ver, updCnt, autoFill, dtId, callback) {
        // 获取用户数据
        var diEnt = new ItbDatumInfoModel;
        diEnt.getInfoByType(userId, type, function(getErr, getRet){
            if(getErr) {
                return callback(getErr, null);
            }

            // 设置新数据
            diEnt.update_by = userId;
            diEnt.data = datum||'';
            diEnt.ver = Number(ver||'0')||0;
            diEnt.upd_cnt = Number(updCnt||'0')||0;
            diEnt.auto_fill = Number(autoFill||'0')||0;
            diEnt.user_id = userId;
            if(getRet && getRet.length>0) {
                var userInfo = getRet[0];
                //var userData = JSON.parse(userInfo.data||'{}');

                // 更新db用户数据
                diEnt.info_id = userInfo.info_id;
                diEnt.updateToDB(function(updErr){
                    return callback(updErr,null);
                });

            } else {
                // 新建用户数据
                diEnt.dt_id = dtId;
                diEnt.saveToDB(function(insErr, newId){
                    return callback(insErr, null);
                });
            }
        });
    };

    /**
     * 获取对应设备类型的最新 app 版本信息
     *
     * @param device 设备
     * */
    usersUtil.getLastVersion_v5_7 = function(device, callback) {
        (new ItbProductVer).getLastAppVersion(device, callback);
    };

    //-------------------------------------------------------------
    // 获取用户所有信息, 暂时包括, 基本信息, 第三方信息, vip 信息, 环信账户信息等
    /**
     *
     * * "data": {
     *   "userId": 1055,
     *   "userType": 1,
     *   "mobile": 13297922921,
     *   "registerUUID": "QWERTYUIOP-iOS",
     *   "nickName": "哈哈",
     *   "headUrl": "http://www.itbour.com/header/xxx.png",
     *   "userSign": "我就是不写签名咋地了",
     *   "accessory": [
     *    {
     *       "platform": 1,
     *       "nickName": "平台一昵称",
     *       "headerUrl": "平台一头像",
     *       "field1": "平台一字段一",
     *       "filed2": "平台一字段二",
     *        "field3": "平台一字段三",
     *       "field4": "平台一字段四",
     *        "field5": "平台一字段五"
     *      }
     *    ],
     *    "vipInfo" : {"vip" : 10,"expiry_time" : "2017-12-8 14:28”}, // 非 vip 字段为空
     *    "partnerInfo" : {"partner_id" : 985,"level" : 10}, // 非合伙人, 字段为空
     *    "hxInfo" : {"hx_id" : 211,"hx_psw" : “xcset”},  // 没有则创建
     *  }
     * }"
     * */
    usersUtil.getUsersDetailInfo_v6_0 = function(userId, mobile, callback) {

        // 获取基本信息, 和 第三方账户信息

        var userModel = new ItbUserModel();
        if(userId > 0) userModel.user_id = userId;
        if(mobile > 0) userModel.mobile = mobile;

        // 查询用户信息
        userModel.findFromDB(function(findUserErr, users){
            if(findUserErr) {
                return callback(findUserErr, null);
            }
            if (!users || users.length <= 0) {
                return callback('无此用户信息', null);
            }
            // 查询用户第三方账户信息
            userModel.findWithPlatformInfo(function(baseError, baseInfos){
                if(baseError) {
                    return callback(baseError, null);
                }
                // 组织用户基础信息
                var retData = null;
                if(baseInfos.length > 0) {
                    retData = usersUtil.organizeUserInfo_v5_2(baseInfos);
                }
                if(!retData) {
                    retData = usersUtil.initOrganizeUserInfo_v5_2(users[0]);
                }
                // 查询用户 合伙人, 环信账户等信息
                async.series(
                    [
                        function(callback) {
                            usersUtil.getUserMemberInfo_v6_0(retData.userId,function(error, data){callback(error,data);});
                        },
                        function(callback) {
                            usersUtil.getCityPartnermessage_v5_4(retData.userId,function(error,data){callback(error,data)});
                        },
                        function(callback) {
                            // modify by wangjun 2017-12-29, 环信失效, 避免报错
                            usersUtil.getUserHxInfo(retData.userId, function(error,data){callback(null,data)});
                        },
                        function(callback) {
                            usersUtil.getCityPartnerInfo_v5_4(retData.userId, function(error,data){callback(error,data)});
                        }
                    ],
                    function(error, result){

                        if(error) {
                            return callback(error, null);
                        }
                        // vip
                        retData.vipInfo = result[0] || {};

                        // 合伙人
                        if(result[1] && result[1].length >0) {
                            retData.partnerInfo = result[1][0] || {};
                        }else{
                            retData.partnerInfo = {};
                        }
                        // 环信
                        retData.hxInfo = result[2] || {};
                        // 合伙人申请状态
                        if(result[3] && result[3].length > 0) {
                            var stateInfo = result[3][0];
                            retData.partnerInfo.state = stateInfo.state;
                        } else {
                            retData.partnerInfo.state=-1;
                        }

                        return callback(error, retData);
                    });
            });
        });
    };

    /**
     * 获取用户会员信息
     *
     * @param userId 用户唯一标识
     * @param callback 查询回调
     *
     *          error 查询失败
     *          data  vip 信息, 类似于: {"vip" : 10,"expiry_time" : "2017-12-8 14:28”}
     *
     * */
    usersUtil.getUserMemberInfo_v6_0 = function(userId, callback){
        (new ItbMemberModel()).getUserMemberInfo(userId, function(error, data){

            if(error || !data) {
                return callback(error, data);
            }

            var retInfo = {};
            retInfo.vip = data.vip;
            retInfo.expiry_time = (new moment(data.expiry_time)).format('YYYY-MM-DD HH:mm:ss');
            return callback(error, retInfo);
        });
    };
    //----------------------------------------------------------------

    // 更新IAP订单状态
    usersUtil.updateVipOrderState_v6_0 = function(userId, orderId, state, transactionId, receiptData, exceptionType,callback){
        if(receiptData) receiptData = receiptData.replace(/ /g,'+'); // 前置验证逻辑

        // *** 保存验证 log 至数据库 ***
        var insEnt = new ItbPaymentHisModel({
            type: 40,// 订单类型
            trade_obj_id: orderId,
            state: state,// 支付成功
            pay_platform: 30,// 苹果内购
            desc: 'app update IAP log',
            pay_info1: state,
            pay_info2: receiptData ||'',
            pay_info6: transactionId ||'',
            update_by: userId
        });
        insEnt.saveToDB(function(saveLogErr, result){
            if(saveLogErr) {
                return callback(saveLogErr, null);
            }

            // 1. 查询订单信息
            var orderModel = new ItbTradeOrderModel({
                order_id : orderId,
                del_flg : 0
            });
            // 更新状态传入: 11 支付成功, 12 支付失败
            // '订单状态:10待支付、11已支付、12支付失败、20制作中、30配送中、40完成、50取消',
            orderModel.findFromDB(function(findOrderErr, orders){
                if(findOrderErr || !orders || orders.length == 0) {
                    return callback(findOrderErr, 12)
                }
                var order = orders[0];
                // 2. 移动端更新状态, 认为支付失败, 无需验证, 直接更新支付失败
                if(state != 11) {
                    payUtil.updOrderState(order.order_id,
                        40,// 虚拟商品
                        50,// 订单取消
                        order.total_fee||0,
                        userId,
                        function(updErr, updRet){
                            return callback(updErr, 12); // 取消后返回订单失败
                        }
                    );
                } else {
                    // 3. 如果更新状态为支付成功, 需通过苹果服务器验证是否真的支付成功
                    usersUtil.checkIAPTransactionState(userId, orderId, transactionId, receiptData, function(checkIAPErr, transaction, validateRet){
                        if(checkIAPErr) {
                            return callback(checkIAPErr, null);
                        }

                        // 支付失败
                        if(!transaction || transaction.cancellation_date) {
                            payUtil.updOrderState(order.order_id,
                                40,// 虚拟商品
                                50,// 订单取消
                                order.total_fee||0,
                                userId,
                                function(updErr, updRet){
                                    return callback(updErr, 12); // 取消后返回订单失败
                                }
                            );
                        } else {
                            // 支付成功
                            // 添加支付历史纪录
                            validateRet = validateRet ? validateRet : {};
                            var insEnt = new ItbPaymentHisModel({
                                type: 40,// 订单类型
                                trade_obj_id: orderId,
                                trade_obj_no: order.order_no || '',// TODO orderNo
                                state: 11,// 支付成功
                                pay_platform: 30,// 苹果内购
                                desc: 'SUCCESS',
                                pay_info1: 11,
                                pay_info2: receiptData ||'',
                                pay_info3: transaction.product_id||'',
                                pay_info4: transaction.transaction_id||'', //
                                pay_info5: transaction.quantity||'',
                                pay_info6: transaction.original_transaction_id||'',
                                pay_info7: transaction.purchase_date||'',
                                pay_info8: transaction.purchase_date_ms||'',
                                pay_info9: transaction.purchase_date_pst||'',
                                pay_info10: transaction.original_purchase_date||'',
                                pay_info11: transaction.original_purchase_date_ms||'',
                                pay_info12: transaction.original_purchase_date_pst||'',
                                pay_info13: transaction.is_trial_period||'', //
                                pay_info14: validateRet.environment||'',
                                pay_info15: validateRet.receipt_type||0,
                                pay_info16: validateRet.adam_id||'',
                                pay_info17: validateRet.app_item_id||0,
                                pay_info18: validateRet.bundle_id||'',
                                pay_info19: validateRet.application_version||0,
                                pay_info20: validateRet.download_id||0,
                                pay_info21: validateRet.version_external_identifier||'',
                                pay_info22: validateRet.receipt_creation_date||'',
                                pay_info23: validateRet.request_date||'',
                                pay_info24: validateRet.original_purchase_date||'',
                                pay_info25: validateRet.original_application_version ||'',
                                update_by: userId
                            });
                            insEnt.saveToDB(function(insErr, newHisId){
                                if(insErr) {
                                    console.log("usersUtil.js [updateVipOrderState_v6_0] Ins PayHis Err: "+insErr);
                                }
                                // 更新订单为支付成功
                                payUtil.updOrderState(orderId, 40/*虚拟商品*/, 11/*支付成功*/, order.total_fee, userId, function(updErr, updRet){

                                    // 强制更新优惠券状态
                                    usersUtil.forceUpdateOrderCouponStateByOrderId(orderId, function(updateCouponErr){
                                        // 再更新订单为完成
                                        payUtil.updOrderState(orderId, 40, 40/*订单完成*/, order.total_fee, userId, function(updErr2, updRet2){
                                            // 更新vip会员信息
                                            payUtil.updVipExpiryInfo(userId, orderId, function(updErr3, updRet3){

                                                return callback(updErr || updateCouponErr || updErr2||updErr3,  11);
                                            });
                                        });
                                    });
                                });
                            });
                        }
                    });
                }
            });
        });
    };
    //----------------------------------------------------------------
    /***
     * 通过苹果服务器验证是否真的支付成功
     *
     * @param userId 用户唯一标识
     * @param orderId 订单唯一标识
     * @param transactionId 交易唯一标识
     * @param receiptData 验证凭据
     * @param callback 验证回调
     *          error : 验证出错
     *          currentTransaction :  当前交易
     *          result: 验证拿到的所有数据
     *
     * */
    usersUtil.checkIAPTransactionState = function (userId, orderId, transactionId, receiptData, callback) {

        if(!transactionId || transactionId.length == 0) {
            return callback(null, 12);
        }

        // 根据receiptData 向苹果服务器验证
        // 1. 验证生产环境
        if(receiptData) receiptData = receiptData.replace(/ /g,'+');

        var param = {
            "receipt-data" : receiptData
        };

        function validateIAP(result) {
            /** IAP 返回状态码
             21000	App Store不能读取你提供的JSON对象
             21002	receipt-data域的数据有问题
             21003	receipt无法通过验证
             21004	提供的shared secret不匹配你账号中的shared secret
             21005	receipt服务器当前不可用
             21006	receipt合法，但是订阅已过期。服务器接收到这个状态码时，receipt数据仍然会解码并一起发送
             21007	receipt是Sandbox receipt，但却发送至生产系统的验证服务
             21008	receipt是生产receipt，但却发送至Sandbox环境的验证服务
             * */
            if(Number(result.status) != 0) {
                console.log("usersUtil.js [checkIAPTransactionState] err: " + result.status);
                return callback("validate IAP transaction err", null);
            }
            // 获取该用户的所有交易信息
            var inApp = result.receipt.in_app;
            if (!inApp || inApp.length ==0) {
                return callback(null, 12); // 没有支付记录, 认定失败
            }

            var  state = 12; // 默认支付失败
            var currentTransaction = null;
            for(var i=0; i < inApp.length; i++) {
                var transaction = inApp[i];

                /** IAP 单笔交易信息字段类型及含义
                 * transaction_id	            integer	交易号
                 * original_transaction_id	    integer	原始交易号
                 * product_id	                string	商品标识符
                 * quantity	                    integer	数量
                 * purchase_date	            string	购买日期
                 * original_purchase_date	    string	原始购买日期
                 * purchase_date_ms	            integer	购买日期(ms)
                 * original_purchase_date_ms	integer	原始购买日期(ms)
                 * purchase_date_pst	        string	购买日期(pst)
                 * original_purchase_date_pst	string	原始购买日期(pst)
                 * cancellation_date	        string	取消购买的日期 (如果存在, 则标识该笔交易被取消)
                 * */
                // 存在该订单, 且该订单没有取消
                if(transaction.transaction_id == transactionId && !transaction.cancellation_date) {
                     currentTransaction = transaction;
                    // todo 此处建议根据 product_id 查询支付的商品价格, 看是否与订单价格相同
                    break;
                }
            }
            return callback(null, currentTransaction, result);
        }
        // 先验证正式环境
        var testIAPServer = "https://sandbox.itunes.apple.com/verifyReceipt"; // 沙盒环境
        var publishIAPServer = "https://buy.itunes.apple.com/verifyReceipt";
        superagent.post(publishIAPServer)
            .send(param)
            .end(function(chkPublishErr, publishRes){
                if(chkPublishErr) {
                    return callback(chkPublishErr, null);
                }
                var result = JSON.parse(publishRes.text);
                // 如果发现沙盒环境的 receipt 被发送到了正式验证, 则切换到沙盒验证接口验证
                if(Number(result.status) == 21007) {
                    console.log("=== 正式环境验证了沙盒环境的交易, 切换回沙盒环境验证 ===");
                    superagent.post(testIAPServer)
                        .send(param)
                        .end(function(chkSandBoxErr, sandboxRes){
                            if(chkSandBoxErr) {
                                return callback(chkSandBoxErr, null);
                            }
                            return validateIAP(JSON.parse(sandboxRes.text));
                        });
                    return;
                }
                return validateIAP(result);
            });
    };
    // 分享领券
    usersUtil.getShareAwardCoupon_v6_0 = function(userId, callback){

        // 确认用户是否有效
        var entity = new ItbUserModel({
            user_id : userId,
            del_flg : 0
        });

        entity.findFromDB(function(findUserErr, users){
            if(findUserErr) {
                return callback(findUserErr, null);
            }
            if(!users || users.length == 0) {
                return callback('用户不存在', null);
            }
            // 1. 频率检测
            usersUtil.chkCouponByUserId(userId, null, function(checkErr, chkret){
                if(checkErr) {
                    return callback(checkErr, null);
                }

                if(chkret) {
                    return callback("您今日分享优惠券已领", null);
                }
                // 2. 领取优惠码
                callFuncUtil.getCouponFromCache(20, 1, function(getCodesErr, codes){
                    if(getCodesErr) {
                        return callback(getCodesErr, null);
                    }
                    // 过滤空值
                    codes = codes.filter(function(n){if(n == null || n == undefined || n.length == 0) {return false;}return true;});

                    if(!codes || codes.length == 0) {
                        return callback("暂无优惠券可领", null);
                    }
                    // 3. 发放优惠券到用户
                    printUtil.exchgDrawCouponByCodes_v6_0(userId, codes, function(bindErr, result){
                        return callback(bindErr, result);
                    });
                });
            });
        });
    };

    /* 兑换抽奖抽到的优惠码
     * 参数: userId	用户唯一标识
     * 参数: code	兑换码
     * 返回值:
     {
     "data":{
     "id":986, // 优惠券唯一标识
     "code":"QWERTPOIUYEV", // 优惠券兑换码, 也可作唯一标识
     "type_desc":"抵扣券", // 优惠券类型描述, 抵扣券, 折扣券, 满减
     "discount_desc":"5.0元",// 优惠券额度, 5元 8折
     "trade_type":10, // 优惠券类型, 10商品订单(印品)，30购买模版(设计)
     "expiry_time":"2017-03-05", // 优惠券过期时间
     "coupon_desc":"暂不抵扣运费", // 优惠券说明, 不抵扣运费, 满10减1
     "reason":"" // 优惠券失效原因, 未失效则为空字符串
     }
     }
     * */
    printUtil.exchgDrawCoupon_v6_0 = function(userId, code, callback){
        var ent = new ItbUserModel({
            user_id:userId,
            del_flg:0
        });
        ent.findFromDB(function(findErr, findRet){
            if(findErr){
                console.log('printUtil.js [getCouponByCode_v5_2] findUser Err:'+findErr);
                return callback(findErr, null);
            }
            if(findRet && findRet.length>0) {
                var userInfo = findRet[0];

                // 获取优惠券信息
                (new ItbCouponModel).getCouponInfoByCode((code||'').toUpperCase(), function(err, retInfo){
                    if(err){
                        console.log('printUtil.js [getCouponByCode_v5_2] getCouponInfoByCode Err:'+err);
                        return callback(err, null);
                    }
                    if(retInfo && retInfo.length>0) {
                        var info = retInfo[0];
                        var retData = printUtil.genCouponRetInfo(info);
                        retData.code = (code||'').toUpperCase();

                        if(info.state==15 && (userInfo.mobile != info.mobile)) {
                            retData.reason = '已领取';
                        }
                        if((info.state==10 || info.state==15) && retData.reason.length==0) {
                            // 绑定用户
                            (new ItbCouponModel).exchgDrawCoupon(userId, userInfo.mobile, info.c_id, null, function(updErr, updRet){
                                return callback(updErr, retData);
                            });
                        } else {
                            return callback(null, retData);
                        }
                    } else {
                        return callback(null, {reason: '无效兑换码'});
                    }
                });

            } else {
                return callback('无效用户', null);
            }
        });
    };
    /* 批量兑换抽奖抽到的优惠券
     * 参数: userId	用户唯一标识
     * 参数: codes	兑换码 数组
     * 返回值:
     {
     "data":{
     "id":986, // 优惠券唯一标识
     "code":"QWERTPOIUYEV", // 优惠券兑换码, 也可作唯一标识
     "type_desc":"抵扣券", // 优惠券类型描述, 抵扣券, 折扣券, 满减
     "discount_desc":"5.0元",// 优惠券额度, 5元 8折
     "trade_type":10, // 优惠券类型, 10商品订单(印品)，30购买模版(设计)
     "expiry_time":"2017-03-05", // 优惠券过期时间
     "coupon_desc":"暂不抵扣运费", // 优惠券说明, 不抵扣运费, 满10减1
     "reason":"" // 优惠券失效原因, 未失效则为空字符串
     }
     }
     * */
    printUtil.exchgDrawCouponByCodes_v6_0 = function(userId, codes, callback){
        var c_codes = JSON.stringify(codes);
        c_codes = c_codes.substring(1, c_codes.length -1);
        (new ItbCouponModel).getCouponInfoByCodes(c_codes, function(err, retInfo){
            if(err){
                console.log('printUtil.js [getCouponByCodes_v5_2] getCouponInfoByCode Err:'+err);
                return callback(err, null);
            }

            if(!retInfo || retInfo.length == 0) {
                return callback(null, {reason:'无效兑换码'});
            }

            var asyncFuncs = [];
            for(var i=0;i<retInfo.length; i++){
                asyncFuncs.push((function (index, one) {
                    return function (asyncCallback) {
                        var code = (codes[index]||'').toUpperCase();
                        //优惠券状态不对, 不予添加
                        if(one.state != 10) {
                            return asyncCallback(null, null);// check?
                        }
                        printUtil.exchgDrawCoupon_v6_0(userId, code, function(err, coupon){
                            return asyncCallback(err, coupon);
                        });
                    }
                })(i, retInfo[i])); // 利用闭包解决动态参数传递问题
            }
            async.parallel(asyncFuncs, function (error, results) {
                if (error) {
                    console.log('printUtil.js [printUtil.get_printData] error: '+error);
                    return callback(error, null);
                }

                var coupons = [];
                for(var i = 0; i < results.length; i ++) {
                    if(results[i] && results && results != null) {
                        coupons.push(results[i]);
                    }
                }
                return callback(null, coupons);
            });
        });
    };
    //--------------------------------设置用户预填资料是否自动填充------------------------------
    usersUtil.setUserDatumAutoFill_v6_0 = function (userId, autoFill, callback) {
        var diEnt = new ItbDatumInfoModel;
        // 个人资料
        diEnt.getInfoByType(userId, 10, function(getErr, getRet){
            if(getErr) {
                return callback(getErr, null);
            }
            // 设置新数据
            diEnt.update_by = userId;
            diEnt.auto_fill = Number(autoFill||'0')||0;
            if(!getRet || getRet.length <= 0) {
                return callback("暂无资料信息, 无法自动填充", null);
            }
            var userInfo = getRet[0];
            // 更新db用户数据
            diEnt.info_id = userInfo.info_id;
            diEnt.updateToDB(function(updErr){
                return callback(updErr,autoFill);
            });
        });
    };


    function getFirstDayOfMonth(yyyy,mm,fmt) {
        var dt = new Date(yyyy,mm-1,1);// 月份下标从0开始
        var mt = moment(dt);
        return mt.format(fmt);
    }
    function getLastDayOfMonth(yyyy,mm,fmt) {
        var dt = new Date(yyyy,mm,1);// 下个月第一天
        var cdt = new Date(dt.getTime()-1000*3600*24);
        var mt = moment(cdt);
        return mt.format(fmt);
    }

    /**
     * 城市合伙人查看在当前月内的、自己注册地址所在区内的所有城市合伙人的销售额（城市合伙人的绑定用户的除去邮费的订单的总额）排行
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     * {
     *        "area":"武汉市洪山区",
     *        "period":"20170601至20170624",
     *        "list":[
     *            {
     *                "rank":989,
     *                "mobile":"188****2619",
     *                "orderSum":100,
     *                "incomeSum":3
     *            }
     *        ],
     *        "pageNum":3,
     *        "totalPage":5
     * }
     */
    usersUtil.getCityPartnerLatestRankList_v6_1=function(userId, pageNum, pageSize, callback){
        // 获取目标地区
        (new ItbPartnerApplicationModel).getPartnerAppArea(userId, function(getErr, retAreaInfo){
            if(getErr) {
                return callback(getErr, null);
            }

            if(retAreaInfo && retAreaInfo.length>0) {
                var areaInfo = retAreaInfo[0];
                var fullAreaNm = (areaInfo.prov_name||'')+(areaInfo.city_name||'')+(areaInfo.dist_name||'');
                if((areaInfo.prov_name||'')==(areaInfo.city_name||'')) {
                    fullAreaNm = (areaInfo.city_name||'')+(areaInfo.dist_name||'');
                }

                var dt = new Date();
                var period = getFirstDayOfMonth(dt.getFullYear(),dt.getMonth()+1,'YYYY/MM/DD')+
                        '至'+ moment(dt).format('YYYY/MM/DD');

                // 获取排行
                var rankEnt = new ItbPartnerSaleRankModel;
                rankEnt.getCityPartnerLatestRankList(areaInfo.prov, areaInfo.city, areaInfo.dist, pageNum, pageSize,
                    function(getErr2, retRankInfo){
                        if(getErr2) {
                            return callback(getErr2, null);
                        }

                        // 总数
                        rankEnt.getCityPartnerLatestRankListCnt(areaInfo.prov, areaInfo.city, areaInfo.dist,
                            function(getErr3, count){
                                if(getErr3) {
                                    return callback(getErr3, null);
                                }

                                // 返回值
                                var retData = {
                                    area: fullAreaNm||'未知',
                                    period: period,
                                    list: [],
                                    pageNum: pageNum,
                                    totalPage: Math.floor((count-1)/pageSize)+1
                                };

                                if(retRankInfo && retRankInfo.length>0) {
                                    for(var i=0;i<retRankInfo.length;i++) {
                                        var info = retRankInfo[i];
                                        var mobile = info.mobile;
                                        if(info.user_id != userId) {
                                            mobile += "";
                                            mobile = mobile.substr(0,3)+'****'+mobile.substr(7);
                                        }
                                        retData.list.push({
                                            rank: info.rank||0,
                                            mobile: mobile,
                                            orderSum: info.sale_fee||0,
                                            incomeSum: info.income||0,
                                        });
                                    }
                                }

                                return callback(null, retData);
                            }
                        );
                    }
                );

            } else {
                return callback('未获取到地区信息', null);
            }
        });
    };

    /**
     * 城市合伙人查看每个月、自己注册地址所在区内的所有城市合伙人的销售额（城市合伙人的绑定用户的除去邮费的订单的总额）的销售冠军的历史
     * @param userId
     * @param pageNum
     * @param pageSize
     * @return
     * {
     *        "area":"武汉市洪山区",
     *        "list":[
     *            {
     *                "year":2017,
     *                "month":"7",
     *                "mobile":"188****2619",
     *                "orderSum":100,
     *                "incomeSum":3
     *            }
     *        ],
     *        "pageNum":3,
     *        "totalPage":5
     * }
     */
    usersUtil.getCityPartnerRankHistory_v6_1=function(userId, pageNum, pageSize, callback){
        // 获取目标地区
        (new ItbPartnerApplicationModel).getPartnerAppArea(userId, function(getErr, retAreaInfo){
            if(getErr) {
                return callback(getErr, null);
            }

            if(retAreaInfo && retAreaInfo.length>0) {
                var areaInfo = retAreaInfo[0];
                var fullAreaNm = (areaInfo.prov_name||'')+(areaInfo.city_name||'')+(areaInfo.dist_name||'');
                if((areaInfo.prov_name||'')==(areaInfo.city_name||'')) {
                    fullAreaNm = (areaInfo.city_name||'')+(areaInfo.dist_name||'');
                }

                // 获取排行
                var rankEnt = new ItbPartnerSaleRankModel;
                rankEnt.getTopRankHis(areaInfo.prov, areaInfo.city, areaInfo.dist, pageNum, pageSize,
                    function(getErr2, retRankInfo){
                        if(getErr2) {
                            return callback(getErr2, null);
                        }

                        // 总数
                        rankEnt.getTopRankHisCnt(areaInfo.prov, areaInfo.city, areaInfo.dist,
                            function(getErr3, count){
                                if(getErr3) {
                                    return callback(getErr3, null);
                                }

                                // 返回值
                                var retData = {
                                    area: fullAreaNm||'未知',
                                    list: [],
                                    pageNum: pageNum,
                                    totalPage: Math.floor((count-1)/pageSize)+1
                                };

                                if(retRankInfo && retRankInfo.length>0) {
                                    for(var i=0;i<retRankInfo.length;i++) {
                                        var info = retRankInfo[i];
                                        var mobile = info.mobile;
                                        if(info.user_id != userId) {
                                            mobile += "";
                                            mobile = mobile.substr(0,3)+'****'+mobile.substr(7);
                                        }
                                        retData.list.push({
                                            year: info.year||'未知',
                                            month: info.month||'未知',
                                            mobile: mobile,
                                            orderSum: info.sale_fee||0,
                                            incomeSum: info.income||0,
                                        });
                                    }
                                }

                                return callback(null, retData);
                            }
                        );
                    }
                );

            } else {
                return callback('未获取到地区信息', null);
            }
        });
    };

    /**
     * 根据微信 unionId 获取用户唯一标识, 若不存在则注册
     *
     * @param unionId 微信用户唯一标识
     * @param regInfo 微信用户信息{'nickName':'哈哈', 'headUrl':'http://oss-img.jpg', 'uuid':'QWERTYUIOSDFGHJK-mp' } 等
     * @param callback 回调
     *          err
     *          userId
     * */
    usersUtil.getUserIdByWechatInfoForMiniProgram = function(unionId, regInfo, callback){

        // 1. 查询用户是否存在
        var queryUserModel = new ItbUserModel({
            wechat_token_union : unionId,
            del_flg : 0
        });
        queryUserModel.findFromDB(function(findUserErr, users){
            if(findUserErr) {
                return callback(findUserErr, null);
            }
            // 2.1 如果用户存在, 直接返回
            if(users && users.length > 0) {
                return callback(null, users[0].user_id);
            }

            // 2.2 如果用户不存在, 注册后返回
            var info = {};
            info.wechat_token_union = unionId;
            if(regInfo && regInfo.nickName && regInfo.nickName.length>0) {
                info.wechat_nickname = regInfo.nickName;
            }
            if(regInfo && regInfo.uuid && regInfo.uuid.length>0) {
                info.uuid = regInfo.uuid;
            }
            var inserUserModel = new ItbUserModel(info);

            inserUserModel.saveToDB(function(registerErr, userId){
                if(registerErr) {
                    return callback(registerErr, null);
                }
                return callback(null, userId);
            })
        });
    };

    //
    /**
     * 根据订单状态强制更新优惠券状态
     *
     * @param orderId 订单唯一标识
     * @param callback 回调
     *          error: 更新出错
     *
     * */
    usersUtil.forceUpdateOrderCouponStateByOrderId = function(orderId, callback) {
        (new ItbCouponModel({})).updStateByPaidOrder2(orderId, callback);
    };

    /**
     * 处理只有 userId 异常情况的查询缓存
     *
     * @param userId, 用户唯一标识, 可能存在
     * @param orderId, 订单唯一标识, 可能存在
     * @param state, 订单状态, 可能存在
     * @param transactionId IAP 支付唯一标识, 可能存在
     * @param receiptData, IAP 交易凭据, 可能存在
     * @param exceptionType, 异常状态, 可能不准确
     * @param callback 回调
     *             error: 是否存储成功
     *
     * */
    usersUtil.handleIAPExceptionWithUserId = function(userId, orderId, state, transactionId, receiptData,exceptionType, callback) {
        if(receiptData) receiptData = receiptData.replace(/ /g,'+'); // 前置验证逻辑

        // *** 保存异常 log 至数据库 ***
        var insEnt = new ItbPaymentHisModel({
            type: 40,// 订单类型
            trade_obj_id: orderId || 0,
            state: state || 0,// 支付成功
            pay_platform: 30,// 苹果内购
            desc: 'app exception IAP log with exceptionType: ' + exceptionType,
            pay_info1: state || '',
            pay_info2: receiptData ||'',
            pay_info6: transactionId ||'',
            update_by: userId || ''
        });
        insEnt.saveToDB(function(saveLogErr, result){
            if(saveLogErr) {
                return callback(saveLogErr, null);
            }
            return callback(null);
        });
    };


    // /**
    //  * 获取订单物流信息
    //  * @param userId
    //  * @param orderId
    //  * @return
    //  *  {
    // "orderId": 986,
    // "name": "中通快递",
    // "no": "33982123",
    // "state": 0, //'当前快递状态：0未知，1揽件中，2在途中，3派件中，4已签收，5派件失败/拒签，6疑难/问题件，7退回',
    // "list": [
    //   {
    //     "time": "2017-09-29 09:27:03",
    //     "status": "[武汉市] 快件已到达武昌关南,业务员曙光星城周俊[15717167682]正在派件"
    //   }
    //     ]
    //     }
    // */
    // usersUtil.getLogisticsInfo = function(userId,orderId,callback){
    //     (new ItbExpTrackInfoModel).getLogisticsInfo(userId,orderId, function(getErr, LogisticsInfo){
    //         if(getErr) {
    //             return callback(getErr, null);
    //         }
    //         // 如果有物流查询记录信息, 则根据物流查询记录信息获取物流公司信息和快递记录
    //         if(LogisticsInfo && LogisticsInfo.length >0){
    //             var excId = LogisticsInfo[0].exc_id;
    //             //获取物流公司信息
    //             (new ItbExpTrackInfoModel).getLogisticsCompanyInfo(excId,function(getErr2,logisticsCompanyInfo){
    //                 if(getErr2) {
    //                     return callback(getErr2, null);
    //                 }
    //                 var para = {};
    //                 para.orderId = LogisticsInfo[0].trade_obj_id;
    //                 para.name = logisticsCompanyInfo[0].name;
    //                 para.no = LogisticsInfo[0].ex_tracking_no;
    //                 para.state = LogisticsInfo[0].state;
    //                 para.logisticsPhone = logisticsCompanyInfo[0].mobile;
    //                 var data = LogisticsInfo[0].data || "";
    //                 para.list = [];
    //                 var logData = JSON.parse(LogisticsInfo[0].data || '{}');
    //                 if (logData.result && logData.result.list) {
    //                     para.list = logData.result.list;
    //                 }
    //                 return callback(getErr2, para);
    //             });
    //         }
    //         // 有物流单号但是还没有查询过, 不直接找查询记录获取信息, 从子订单中获取物流公司 id, 查询物流公司信息
    //         else  {
    //             printUtil.get_printProductInfo_v5_5(orderId, function(error,data){
    //                 if(error || !data || data.length <= 0) {
    //                     return callback(error || '该无子订单信息', null);
    //                 }
    //                 var excId = data[0].exc_id;
    //                 if(!excId) {
    //                     return callback(null, {});
    //                 }
    //                 //获取物流公司信息
    //                 (new ItbExpTrackInfoModel).getLogisticsCompanyInfo(excId,function(getErr2,logisticsCompanyInfo){
    //                     if(getErr2 || !logisticsCompanyInfo || logisticsCompanyInfo.length <=0) {
    //                         return callback(getErr2 || '无此快递公司', null);
    //                     }
    //                     var para = {};
    //                     para.orderId = orderId;
    //                     para.name = logisticsCompanyInfo[0].name;
    //                     para.no = data[0].tracking_no;
    //                     para.state = 1; // 默认揽件中: 当前快递状态：0未知，1揽件中，2在途中，3派件中，4已签收，5派件失败/拒签，6疑难/问题件，7退回
    //                     para.logisticsPhone = logisticsCompanyInfo[0].mobile;
    //                     para.list = [];
    //                     return callback(getErr2, para);
    //                 });
    //             });
    //         }
    //     })
    // };

    return usersUtil;
})();

module.exports = usersUtil;